mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-04-20 18:14:28 +08:00
算力配置功能已完成
This commit is contained in:
@@ -80,7 +80,6 @@ type BaseConfig struct {
|
||||
LumaPower int `json:"luma_power,omitempty"` // Luma 生成视频消耗算力
|
||||
KeLingPowers map[string]int `json:"keling_powers,omitempty"` // 可灵生成视频消耗算力
|
||||
AdvanceVoicePower int `json:"advance_voice_power,omitempty"` // 高级语音对话消耗算力
|
||||
PromptPower int `json:"prompt_power,omitempty"` // 生成提示词消耗算力
|
||||
|
||||
WechatCardURL string `json:"wechat_card_url,omitempty"` // 微信客服地址
|
||||
|
||||
@@ -94,7 +93,6 @@ type BaseConfig struct {
|
||||
Copyright string `json:"copyright"` // 版权信息
|
||||
DefaultNickname string `json:"default_nickname"` // 默认昵称
|
||||
ICP string `json:"icp"` // ICP 备案号
|
||||
MarkMapText string `json:"mark_map_text"` // 思维导入的默认文本
|
||||
|
||||
EnabledVerify bool `json:"enabled_verify"` // 是否启用验证码
|
||||
EmailWhiteList []string `json:"email_white_list"` // 邮箱白名单列表
|
||||
|
||||
@@ -140,17 +140,15 @@ func (h *ConfigHandler) UpdateBase(c *gin.Context) {
|
||||
// UpdatePower 更新系统配置
|
||||
func (h *ConfigHandler) UpdatePower(c *gin.Context) {
|
||||
var data struct {
|
||||
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
|
||||
DailyPower int `json:"daily_power,omitempty"` // 每日签到赠送算力
|
||||
InvitePower int `json:"invite_power,omitempty"` // 邀请新用户赠送算力值
|
||||
MjPower int `json:"mj_power,omitempty"` // MJ 绘画消耗算力
|
||||
MjActionPower int `json:"mj_action_power,omitempty"` // MJ 操作(放大,变换)消耗算力
|
||||
SdPower int `json:"sd_power,omitempty"` // SD 绘画消耗算力
|
||||
SunoPower int `json:"suno_power,omitempty"` // Suno 生成歌曲消耗算力
|
||||
LumaPower int `json:"luma_power,omitempty"` // Luma 生成视频消耗算力
|
||||
KeLingPowers map[string]int `json:"keling_powers,omitempty"` // 可灵生成视频消耗算力
|
||||
AdvanceVoicePower int `json:"advance_voice_power,omitempty"` // 高级语音对话消耗算力
|
||||
PromptPower int `json:"prompt_power,omitempty"` // 生成提示词消耗算力
|
||||
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
|
||||
DailyPower int `json:"daily_power,omitempty"` // 每日签到赠送算力
|
||||
InvitePower int `json:"invite_power,omitempty"` // 邀请新用户赠送算力值
|
||||
MjPower int `json:"mj_power,omitempty"` // MJ 绘画消耗算力
|
||||
MjActionPower int `json:"mj_action_power,omitempty"` // MJ 操作(放大,变换)消耗算力
|
||||
SdPower int `json:"sd_power,omitempty"` // SD 绘画消耗算力
|
||||
SunoPower int `json:"suno_power,omitempty"` // Suno 生成歌曲消耗算力
|
||||
LumaPower int `json:"luma_power,omitempty"` // Luma 生成视频消耗算力
|
||||
KeLingPowers map[string]int `json:"keling_powers,omitempty"` // 可灵生成视频消耗算力
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
@@ -166,8 +164,6 @@ func (h *ConfigHandler) UpdatePower(c *gin.Context) {
|
||||
h.sysConfig.Base.SunoPower = data.SunoPower
|
||||
h.sysConfig.Base.LumaPower = data.LumaPower
|
||||
h.sysConfig.Base.KeLingPowers = data.KeLingPowers
|
||||
h.sysConfig.Base.AdvanceVoicePower = data.AdvanceVoicePower
|
||||
h.sysConfig.Base.PromptPower = data.PromptPower
|
||||
|
||||
err := h.Update(types.ConfigKeySystem, h.sysConfig.Base)
|
||||
if err != nil {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"geekai/core/middleware"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
"geekai/service/crawler"
|
||||
"geekai/service/dalle"
|
||||
"geekai/service/oss"
|
||||
"geekai/store/model"
|
||||
@@ -66,7 +65,6 @@ func (h *FunctionHandler) RegisterRoutes() {
|
||||
group.POST("weibo", h.WeiBo)
|
||||
group.POST("zaobao", h.ZaoBao)
|
||||
group.POST("dalle3", h.Dall3)
|
||||
group.POST("websearch", h.WebSearch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,140 +187,140 @@ func (h *FunctionHandler) Dall3(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var params map[string]interface{}
|
||||
if err := c.ShouldBindJSON(¶ms); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
// var params map[string]interface{}
|
||||
// if err := c.ShouldBindJSON(¶ms); err != nil {
|
||||
// resp.ERROR(c, types.InvalidArgs)
|
||||
// return
|
||||
// }
|
||||
|
||||
logger.Debugf("绘画参数:%+v", params)
|
||||
var user model.User
|
||||
res := h.DB.Where("id = ?", params["user_id"]).First(&user)
|
||||
if res.Error != nil {
|
||||
resp.ERROR(c, "当前用户不存在!")
|
||||
return
|
||||
}
|
||||
// logger.Debugf("绘画参数:%+v", params)
|
||||
// var user model.User
|
||||
// res := h.DB.Where("id = ?", params["user_id"]).First(&user)
|
||||
// if res.Error != nil {
|
||||
// resp.ERROR(c, "当前用户不存在!")
|
||||
// return
|
||||
// }
|
||||
|
||||
if user.Power < h.App.SysConfig.Base.DallPower {
|
||||
resp.ERROR(c, "创建 DALL-E 绘图任务失败,算力不足")
|
||||
return
|
||||
}
|
||||
// if user.Power < h.App.SysConfig.Base.DallPower {
|
||||
// resp.ERROR(c, "创建 DALL-E 绘图任务失败,算力不足")
|
||||
// return
|
||||
// }
|
||||
|
||||
// create dall task
|
||||
prompt := utils.InterfaceToString(params["prompt"])
|
||||
task := types.DallTask{
|
||||
UserId: user.Id,
|
||||
Prompt: prompt,
|
||||
ModelId: 0,
|
||||
ModelName: "dall-e-3",
|
||||
TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
|
||||
N: 1,
|
||||
Quality: "standard",
|
||||
Size: "1024x1024",
|
||||
Style: "vivid",
|
||||
Power: h.App.SysConfig.Base.DallPower,
|
||||
}
|
||||
job := model.DallJob{
|
||||
UserId: user.Id,
|
||||
Prompt: prompt,
|
||||
Power: h.App.SysConfig.Base.DallPower,
|
||||
TaskInfo: utils.JsonEncode(task),
|
||||
}
|
||||
err := h.DB.Create(&job).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, "创建 DALL-E 绘图任务失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
// // create dall task
|
||||
// prompt := utils.InterfaceToString(params["prompt"])
|
||||
// task := types.DallTask{
|
||||
// UserId: user.Id,
|
||||
// Prompt: prompt,
|
||||
// ModelId: 0,
|
||||
// ModelName: "dall-e-3",
|
||||
// TranslateModelId: h.App.SysConfig.Base.AssistantModelId,
|
||||
// N: 1,
|
||||
// Quality: "standard",
|
||||
// Size: "1024x1024",
|
||||
// Style: "vivid",
|
||||
// Power: h.App.SysConfig.Base.DallPower,
|
||||
// }
|
||||
// job := model.DallJob{
|
||||
// UserId: user.Id,
|
||||
// Prompt: prompt,
|
||||
// Power: h.App.SysConfig.Base.DallPower,
|
||||
// TaskInfo: utils.JsonEncode(task),
|
||||
// }
|
||||
// err := h.DB.Create(&job).Error
|
||||
// if err != nil {
|
||||
// resp.ERROR(c, "创建 DALL-E 绘图任务失败:"+err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
task.Id = job.Id
|
||||
content, err := h.dallService.Image(task, true)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "任务执行失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
// task.Id = job.Id
|
||||
// content, err := h.dallService.Image(task, true)
|
||||
// if err != nil {
|
||||
// resp.ERROR(c, "任务执行失败:"+err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
// 扣减算力
|
||||
err = h.userService.DecreasePower(user.Id, job.Power, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: task.ModelName,
|
||||
Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(job.Prompt, 10)),
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, "扣减算力失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
// // 扣减算力
|
||||
// err = h.userService.DecreasePower(user.Id, job.Power, model.PowerLog{
|
||||
// Type: types.PowerConsume,
|
||||
// Model: task.ModelName,
|
||||
// Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(job.Prompt, 10)),
|
||||
// })
|
||||
// if err != nil {
|
||||
// resp.ERROR(c, "扣减算力失败:"+err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
resp.SUCCESS(c, content)
|
||||
}
|
||||
// resp.SUCCESS(c, content)
|
||||
// }
|
||||
|
||||
// 实现一个联网搜索的函数工具,采用爬虫实现
|
||||
func (h *FunctionHandler) WebSearch(c *gin.Context) {
|
||||
if err := h.checkAuth(c); err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
// // 实现一个联网搜索的函数工具,采用爬虫实现
|
||||
// func (h *FunctionHandler) WebSearch(c *gin.Context) {
|
||||
// if err := h.checkAuth(c); err != nil {
|
||||
// resp.ERROR(c, err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
var params map[string]interface{}
|
||||
if err := c.ShouldBindJSON(¶ms); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
// var params map[string]interface{}
|
||||
// if err := c.ShouldBindJSON(¶ms); err != nil {
|
||||
// resp.ERROR(c, types.InvalidArgs)
|
||||
// return
|
||||
// }
|
||||
|
||||
// 从参数中获取搜索关键词
|
||||
keyword, ok := params["keyword"].(string)
|
||||
if !ok || keyword == "" {
|
||||
resp.ERROR(c, "搜索关键词不能为空")
|
||||
return
|
||||
}
|
||||
// // 从参数中获取搜索关键词
|
||||
// keyword, ok := params["keyword"].(string)
|
||||
// if !ok || keyword == "" {
|
||||
// resp.ERROR(c, "搜索关键词不能为空")
|
||||
// return
|
||||
// }
|
||||
|
||||
// 从参数中获取最大页数,默认为1页
|
||||
maxPages := 1
|
||||
if pages, ok := params["max_pages"].(float64); ok {
|
||||
maxPages = int(pages)
|
||||
}
|
||||
// // 从参数中获取最大页数,默认为1页
|
||||
// maxPages := 1
|
||||
// if pages, ok := params["max_pages"].(float64); ok {
|
||||
// maxPages = int(pages)
|
||||
// }
|
||||
|
||||
// 获取用户ID
|
||||
userID, ok := params["user_id"].(float64)
|
||||
if !ok {
|
||||
resp.ERROR(c, "用户ID不能为空")
|
||||
return
|
||||
}
|
||||
// // 获取用户ID
|
||||
// userID, ok := params["user_id"].(float64)
|
||||
// if !ok {
|
||||
// resp.ERROR(c, "用户ID不能为空")
|
||||
// return
|
||||
// }
|
||||
|
||||
// 查询用户信息
|
||||
var user model.User
|
||||
res := h.DB.Where("id = ?", int(userID)).First(&user)
|
||||
if res.Error != nil {
|
||||
resp.ERROR(c, "用户不存在")
|
||||
return
|
||||
}
|
||||
// // 查询用户信息
|
||||
// var user model.User
|
||||
// res := h.DB.Where("id = ?", int(userID)).First(&user)
|
||||
// if res.Error != nil {
|
||||
// resp.ERROR(c, "用户不存在")
|
||||
// return
|
||||
// }
|
||||
|
||||
// 检查用户算力是否足够
|
||||
searchPower := 1 // 每次搜索消耗1点算力
|
||||
if user.Power < searchPower {
|
||||
resp.ERROR(c, "算力不足,无法执行网络搜索")
|
||||
return
|
||||
}
|
||||
// // 检查用户算力是否足够
|
||||
// searchPower := 1 // 每次搜索消耗1点算力
|
||||
// if user.Power < searchPower {
|
||||
// resp.ERROR(c, "算力不足,无法执行网络搜索")
|
||||
// return
|
||||
// }
|
||||
|
||||
// 执行网络搜索
|
||||
searchResults, err := crawler.SearchWeb(keyword, maxPages)
|
||||
if err != nil {
|
||||
resp.ERROR(c, fmt.Sprintf("搜索失败: %v", err))
|
||||
return
|
||||
}
|
||||
// // 执行网络搜索
|
||||
// searchResults, err := crawler.SearchWeb(keyword, maxPages)
|
||||
// if err != nil {
|
||||
// resp.ERROR(c, fmt.Sprintf("搜索失败: %v", err))
|
||||
// return
|
||||
// }
|
||||
|
||||
// 扣减用户算力
|
||||
err = h.userService.DecreasePower(user.Id, searchPower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: "web_search",
|
||||
Remark: fmt.Sprintf("网络搜索:%s", utils.CutWords(keyword, 10)),
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, "扣减算力失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
// // 扣减用户算力
|
||||
// err = h.userService.DecreasePower(user.Id, searchPower, model.PowerLog{
|
||||
// Type: types.PowerConsume,
|
||||
// Model: "web_search",
|
||||
// Remark: fmt.Sprintf("网络搜索:%s", utils.CutWords(keyword, 10)),
|
||||
// })
|
||||
// if err != nil {
|
||||
// resp.ERROR(c, "扣减算力失败:"+err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
// 返回搜索结果
|
||||
resp.SUCCESS(c, searchResults)
|
||||
// resp.SUCCESS(c, searchResults)
|
||||
}
|
||||
|
||||
// List 获取所有的工具函数列表
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
@@ -45,7 +46,7 @@ func (h *PromptHandler) RegisterRoutes() {
|
||||
group := h.App.Engine.Group("/api/prompt/")
|
||||
|
||||
// 需要用户授权的接口
|
||||
group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis))
|
||||
group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis)).Use(middleware.RateLimitEvery(h.App.Redis, 30*time.Second))
|
||||
{
|
||||
group.POST("lyric", h.Lyric)
|
||||
group.POST("image", h.Image)
|
||||
@@ -69,19 +70,6 @@ func (h *PromptHandler) Lyric(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.App.SysConfig.Base.PromptPower > 0 {
|
||||
userId := h.GetLoginUserId(c)
|
||||
err = h.userService.DecreasePower(userId, h.App.SysConfig.Base.PromptPower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: h.getPromptModel(),
|
||||
Remark: "生成歌词",
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, content)
|
||||
}
|
||||
|
||||
@@ -99,18 +87,7 @@ func (h *PromptHandler) Image(c *gin.Context) {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
if h.App.SysConfig.Base.PromptPower > 0 {
|
||||
userId := h.GetLoginUserId(c)
|
||||
err = h.userService.DecreasePower(userId, h.App.SysConfig.Base.PromptPower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: h.getPromptModel(),
|
||||
Remark: "生成绘画提示词",
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, strings.Trim(content, `"`))
|
||||
}
|
||||
|
||||
@@ -129,19 +106,6 @@ func (h *PromptHandler) Video(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.App.SysConfig.Base.PromptPower > 0 {
|
||||
userId := h.GetLoginUserId(c)
|
||||
err = h.userService.DecreasePower(userId, h.App.SysConfig.Base.PromptPower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: h.getPromptModel(),
|
||||
Remark: "生成视频脚本",
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, strings.Trim(content, `"`))
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
<div class="cell-item">License Key</div>
|
||||
</template>
|
||||
{{ license.key }}
|
||||
<el-tooltip content="复制" placement="top">
|
||||
<i class="iconfont icon-copy ml-2 cursor-pointer" @click="copy(license.key)"></i>
|
||||
</el-tooltip>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
@@ -105,6 +108,11 @@ const active = () => {
|
||||
ElMessage.error(e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const copy = (text) => {
|
||||
navigator.clipboard.writeText(text)
|
||||
ElMessage.success('复制成功')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,18 +1,48 @@
|
||||
<template>
|
||||
<div class="container py-3 px-10" v-loading="loading">
|
||||
<el-tabs v-model="active">
|
||||
<el-tabs v-model="active" type="border-card">
|
||||
<el-tab-pane label="支付宝" name="alipay">
|
||||
<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.sandbox" /></el-form-item>
|
||||
<el-form-item label="AppId"><el-input v-model="alipay.app_id" /></el-form-item>
|
||||
<template #label>
|
||||
<div class="d-flex align-items-center text-blue-600">
|
||||
<i class="iconfont icon-alipay"></i>
|
||||
<span class="ms-2">支付宝</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="rounded-md bg-blue-100 p-3 text-gray-500 border-blue-500 border-2 text-base">
|
||||
如果你不知道怎么获取这些配置信息,请参考文档:
|
||||
<a
|
||||
href="https://docs.geekai.me/plus/config/payment.html#%E6%94%AF%E4%BB%98%E5%AE%9D%E9%85%8D%E7%BD%AE"
|
||||
target="_blank"
|
||||
>支付宝配置</a
|
||||
>。
|
||||
</div>
|
||||
|
||||
<el-form :model="alipay" label-width="140px" label-position="top">
|
||||
<el-form-item label="商户ID"><el-input v-model="alipay.app_id" /></el-form-item>
|
||||
<el-form-item label="商户私钥"
|
||||
><el-input v-model="alipay.private_key" type="textarea" :rows="5"
|
||||
/></el-form-item>
|
||||
<el-form-item label="支付宝公钥"
|
||||
><el-input v-model="alipay.alipay_public_key" type="textarea" :rows="3"
|
||||
/></el-form-item>
|
||||
<el-form-item label="回调域名"><el-input v-model="alipay.domain" /></el-form-item>
|
||||
<el-form-item
|
||||
label="回调域名(<span class='text-red-500'>请确保回调域名已备案且在支付宝应用添加了白名单</span>)"
|
||||
>
|
||||
<template #label>
|
||||
<label class="form-label"
|
||||
>支付回调域名
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
content="请确保回调域名已备案且在支付宝应用添加了白名单"
|
||||
>
|
||||
<i class="iconfont icon-info"></i>
|
||||
</el-tooltip>
|
||||
</label>
|
||||
</template>
|
||||
<el-input v-model="alipay.domain" />
|
||||
</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.sandbox" /></el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="save('alipay')">保存</el-button>
|
||||
<el-button @click="test('alipay')">测试</el-button>
|
||||
@@ -21,16 +51,16 @@
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="微信支付" name="wxpay">
|
||||
<el-form :model="wechat" label-width="140px">
|
||||
<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="商户号(MchId)"><el-input v-model="wechat.mch_id" /></el-form-item>
|
||||
<el-form-item label="证书序列号"><el-input v-model="wechat.serial_no" /></el-form-item>
|
||||
<el-form :model="wxpay" label-width="140px">
|
||||
<el-form-item label="启用通道"><el-switch v-model="wxpay.enabled" /></el-form-item>
|
||||
<el-form-item label="AppId"><el-input v-model="wxpay.app_id" /></el-form-item>
|
||||
<el-form-item label="商户号(MchId)"><el-input v-model="wxpay.mch_id" /></el-form-item>
|
||||
<el-form-item label="证书序列号"><el-input v-model="wxpay.serial_no" /></el-form-item>
|
||||
<el-form-item label="商户私钥"
|
||||
><el-input v-model="wechat.private_key" type="textarea" :rows="3"
|
||||
><el-input v-model="wxpay.private_key" type="textarea" :rows="3"
|
||||
/></el-form-item>
|
||||
<el-form-item label="APIv3 Key"><el-input v-model="wechat.api_v3_key" /></el-form-item>
|
||||
<el-form-item label="回调域名"><el-input v-model="wechat.domain" /></el-form-item>
|
||||
<el-form-item label="APIv3 Key"><el-input v-model="wxpay.api_v3_key" /></el-form-item>
|
||||
<el-form-item label="回调域名"><el-input v-model="wxpay.domain" /></el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="save('wxpay')">保存</el-button>
|
||||
<el-button @click="test('wxpay')">测试</el-button>
|
||||
@@ -54,22 +84,20 @@
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="GeekPay" name="geekpay">
|
||||
<el-form :model="geekpay" label-width="140px">
|
||||
<el-form-item label="启用通道"><el-switch v-model="geekpay.enabled" /></el-form-item>
|
||||
<el-form-item label="商户ID"><el-input v-model="geekpay.app_id" /></el-form-item>
|
||||
<el-tab-pane label="易支付" name="epay">
|
||||
<el-form :model="epay" label-width="140px">
|
||||
<el-form-item label="启用通道"><el-switch v-model="epay.enabled" /></el-form-item>
|
||||
<el-form-item label="商户ID"><el-input v-model="epay.app_id" /></el-form-item>
|
||||
<el-form-item label="商户私钥"
|
||||
><el-input v-model="geekpay.private_key" type="textarea" :rows="3"
|
||||
><el-input v-model="epay.private_key" type="textarea" :rows="3"
|
||||
/></el-form-item>
|
||||
<el-form-item label="网关地址"><el-input v-model="geekpay.api_url" /></el-form-item>
|
||||
<el-form-item label="异步通知URL"><el-input v-model="geekpay.notify_url" /></el-form-item>
|
||||
<el-form-item label="同步回跳URL"><el-input v-model="geekpay.return_url" /></el-form-item>
|
||||
<el-form-item label="支付方式"
|
||||
><items-input v-model:value="geekpay.methods"
|
||||
<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-button type="primary" @click="save('geekpay')">保存</el-button>
|
||||
<el-button @click="test('geekpay')">测试</el-button>
|
||||
<el-button type="primary" @click="save('epay')">保存</el-button>
|
||||
<el-button @click="test('epay')">测试</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
@@ -78,13 +106,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ItemsInput from '@/components/ui/ItemsInput.vue'
|
||||
import { httpGet, httpPost } from '@/utils/http'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const loading = ref(true)
|
||||
const active = ref('alipay')
|
||||
const domain = computed(() => {
|
||||
return window.location.origin
|
||||
})
|
||||
|
||||
const alipay = ref({
|
||||
enabled: false,
|
||||
@@ -94,7 +124,7 @@ const alipay = ref({
|
||||
alipay_public_key: '',
|
||||
domain: '',
|
||||
})
|
||||
const wechat = ref({
|
||||
const wxpay = ref({
|
||||
enabled: false,
|
||||
app_id: '',
|
||||
mch_id: '',
|
||||
@@ -110,28 +140,42 @@ onMounted(() => {
|
||||
.then((res) => {
|
||||
const data = res.data || {}
|
||||
alipay.value = { ...alipay.value, ...(data.alipay || {}) }
|
||||
wechat.value = { ...wechat.value, ...(data.wxpay || data.wechat || {}) }
|
||||
wxpay.value = { ...wxpay.value, ...(data.wxpay || data.wechat || {}) }
|
||||
epay.value = { ...epay.value, ...(data.epay || {}) }
|
||||
|
||||
// 如果 domain 为空,则设置为当前域名
|
||||
if (!alipay.value.domain) {
|
||||
alipay.value.domain = domain.value
|
||||
}
|
||||
if (!wxpay.value.domain) {
|
||||
wxpay.value.domain = domain.value
|
||||
}
|
||||
if (!epay.value.domain) {
|
||||
epay.value.domain = domain.value
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => (loading.value = false))
|
||||
})
|
||||
|
||||
const save = (key) => {
|
||||
const payload = { alipay: alipay.value, wxpay: wechat.value, epay: epay.value }
|
||||
const save = () => {
|
||||
const payload = { alipay: alipay.value, wxpay: wxpay.value, epay: epay.value }
|
||||
httpPost('/api/admin/config/update/payment', payload)
|
||||
.then(() => ElMessage.success('保存成功'))
|
||||
.catch((e) => ElMessage.error(e.message))
|
||||
}
|
||||
|
||||
const test = (key) => {
|
||||
// 后端未提供独立测试接口,保留占位提示
|
||||
ElMessage.info('请在支付端自行验证配置')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.form {
|
||||
padding: 10px 20px 40px 20px;
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
form {
|
||||
padding: 20px;
|
||||
}
|
||||
a {
|
||||
color: #409eff;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -92,42 +92,6 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="label-title">
|
||||
高级语音算力
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
content="使用一次 OpenAI 高级语音对话消耗的算力"
|
||||
raw-content
|
||||
placement="right"
|
||||
>
|
||||
<el-icon>
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.number="system['advance_voice_power']" placeholder="" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="label-title">
|
||||
提示词算力
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
content="生成AI绘图提示词,歌词,视频描述消耗的算力"
|
||||
raw-content
|
||||
placement="right"
|
||||
>
|
||||
<el-icon>
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.number="system['prompt_power']" placeholder="" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div style="padding: 10px">
|
||||
@@ -142,7 +106,6 @@
|
||||
|
||||
<script setup>
|
||||
import { httpGet, httpPost } from '@/utils/http'
|
||||
import { copyObj } from '@/utils/libs'
|
||||
import { InfoFilled } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
@@ -186,12 +149,9 @@ const save = function () {
|
||||
daily_power: system.value.daily_power,
|
||||
mj_power: system.value.mj_power,
|
||||
sd_power: system.value.sd_power,
|
||||
dall_power: system.value.dall_power,
|
||||
suno_power: system.value.suno_power,
|
||||
luma_power: system.value.luma_power,
|
||||
keling_powers: system.value.keling_powers,
|
||||
advance_voice_power: system.value.advance_voice_power,
|
||||
prompt_power: system.value.prompt_power,
|
||||
})
|
||||
.then(() => {
|
||||
ElMessage.success('操作成功!')
|
||||
|
||||
Reference in New Issue
Block a user