mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	fine-tune the new UI theme
This commit is contained in:
		@@ -3,10 +3,11 @@
 | 
			
		||||
## v4.1.8
 | 
			
		||||
 | 
			
		||||
- 功能优化:**UI 全新改版,支持主题切换**。 :rocket: :rocket: :rocket:
 | 
			
		||||
- Bug修复:修复音 Luma API 更新导致任务响应解析失败的错误
 | 
			
		||||
- Bug 修复:修复音 Luma API 更新导致任务响应解析失败的错误
 | 
			
		||||
- 功能优化:支持 Suno v4.0 模型支持
 | 
			
		||||
- Bug修复:修复 Suno 已完成任务删除失败的 错误
 | 
			
		||||
- Bug 修复:修复 Suno 已完成任务删除失败的 错误
 | 
			
		||||
- 功能新增:支持 OpenAI 实时语音通话功能,目前已经支持按次收费,支持管理员设置每次实时语音通话的算力消耗
 | 
			
		||||
- 功能新增:生成提示词需要消耗算力,支持管理员设置每次生成提示词的算力消耗,防止被白嫖
 | 
			
		||||
 | 
			
		||||
## v4.1.7
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -143,13 +143,14 @@ type SystemConfig struct {
 | 
			
		||||
	OrderPayTimeout int    `json:"order_pay_timeout,omitempty"` //订单支付超时时间
 | 
			
		||||
	VipInfoText     string `json:"vip_info_text,omitempty"`     // 会员页面充值说明
 | 
			
		||||
 | 
			
		||||
	MjPower       int `json:"mj_power,omitempty"`        // MJ 绘画消耗算力
 | 
			
		||||
	MjActionPower int `json:"mj_action_power,omitempty"` // MJ 操作(放大,变换)消耗算力
 | 
			
		||||
	SdPower       int `json:"sd_power,omitempty"`        // SD 绘画消耗算力
 | 
			
		||||
	DallPower     int `json:"dall_power,omitempty"`      // DALL-E-3 绘图消耗算力
 | 
			
		||||
	SunoPower     int `json:"suno_power,omitempty"`      // Suno 生成歌曲消耗算力
 | 
			
		||||
	LumaPower     int `json:"luma_power,omitempty"`      // Luma 生成视频消耗算力
 | 
			
		||||
	MjPower           int `json:"mj_power,omitempty"`            // MJ 绘画消耗算力
 | 
			
		||||
	MjActionPower     int `json:"mj_action_power,omitempty"`     // MJ 操作(放大,变换)消耗算力
 | 
			
		||||
	SdPower           int `json:"sd_power,omitempty"`            // SD 绘画消耗算力
 | 
			
		||||
	DallPower         int `json:"dall_power,omitempty"`          // DALL-E-3 绘图消耗算力
 | 
			
		||||
	SunoPower         int `json:"suno_power,omitempty"`          // Suno 生成歌曲消耗算力
 | 
			
		||||
	LumaPower         int `json:"luma_power,omitempty"`          // Luma 生成视频消耗算力
 | 
			
		||||
	AdvanceVoicePower int `json:"advance_voice_power,omitempty"` // 高级语音对话消耗算力
 | 
			
		||||
	PromptPower       int `json:"prompt_power,omitempty"`        // 生成提示词消耗算力
 | 
			
		||||
 | 
			
		||||
	WechatCardURL string `json:"wechat_card_url,omitempty"` // 微信客服地址
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,13 +12,13 @@ import (
 | 
			
		||||
	"geekai/core"
 | 
			
		||||
	"geekai/core/types"
 | 
			
		||||
	"geekai/service"
 | 
			
		||||
	"geekai/service/oss"
 | 
			
		||||
	"geekai/service/suno"
 | 
			
		||||
	"geekai/store/model"
 | 
			
		||||
	"geekai/utils"
 | 
			
		||||
	"geekai/utils/resp"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 提示词生成 handler
 | 
			
		||||
@@ -26,8 +26,6 @@ import (
 | 
			
		||||
 | 
			
		||||
type PromptHandler struct {
 | 
			
		||||
	BaseHandler
 | 
			
		||||
	sunoService *suno.Service
 | 
			
		||||
	uploader    *oss.UploaderManager
 | 
			
		||||
	userService *service.UserService
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +54,15 @@ func (h *PromptHandler) Lyric(c *gin.Context) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if h.App.SysConfig.PromptPower > 0 {
 | 
			
		||||
		userId := h.GetLoginUserId(c)
 | 
			
		||||
		h.userService.DecreasePower(int(userId), h.App.SysConfig.PromptPower, model.PowerLog{
 | 
			
		||||
			Type:   types.PowerConsume,
 | 
			
		||||
			Model:  h.getPromptModel(),
 | 
			
		||||
			Remark: "生成歌词",
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp.SUCCESS(c, content)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +80,14 @@ func (h *PromptHandler) Image(c *gin.Context) {
 | 
			
		||||
		resp.ERROR(c, err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if h.App.SysConfig.PromptPower > 0 {
 | 
			
		||||
		userId := h.GetLoginUserId(c)
 | 
			
		||||
		h.userService.DecreasePower(int(userId), h.App.SysConfig.PromptPower, model.PowerLog{
 | 
			
		||||
			Type:   types.PowerConsume,
 | 
			
		||||
			Model:  h.getPromptModel(),
 | 
			
		||||
			Remark: "生成绘画提示词",
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	resp.SUCCESS(c, strings.Trim(content, `"`))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -92,6 +106,15 @@ func (h *PromptHandler) Video(c *gin.Context) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if h.App.SysConfig.PromptPower > 0 {
 | 
			
		||||
		userId := h.GetLoginUserId(c)
 | 
			
		||||
		h.userService.DecreasePower(int(userId), h.App.SysConfig.PromptPower, model.PowerLog{
 | 
			
		||||
			Type:   types.PowerConsume,
 | 
			
		||||
			Model:  h.getPromptModel(),
 | 
			
		||||
			Remark: "生成视频脚本",
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp.SUCCESS(c, strings.Trim(content, `"`))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -121,3 +144,12 @@ func (h *PromptHandler) MetaPrompt(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	resp.SUCCESS(c, strings.Trim(content, `"`))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PromptHandler) getPromptModel() string {
 | 
			
		||||
	if h.App.SysConfig.TranslateModelId > 0 {
 | 
			
		||||
		var chatModel model.ChatModel
 | 
			
		||||
		h.DB.Where("id", h.App.SysConfig.TranslateModelId).First(&chatModel)
 | 
			
		||||
		return chatModel.Value
 | 
			
		||||
	}
 | 
			
		||||
	return "gpt-4o"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -216,7 +216,7 @@
 | 
			
		||||
          padding 0 20px
 | 
			
		||||
 | 
			
		||||
          .prompt,.failed {
 | 
			
		||||
            padding 6px 0
 | 
			
		||||
            padding 0
 | 
			
		||||
            font-size 16px
 | 
			
		||||
            max-height 80px
 | 
			
		||||
            line-height 28px
 | 
			
		||||
 
 | 
			
		||||
@@ -72,4 +72,8 @@
 | 
			
		||||
    --el-table-row-hover-bg-color: rgba(16, 21, 43, .8);
 | 
			
		||||
    --el-table-current-row-bg-color: rgba(16, 21, 43, .8);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 加载动画
 | 
			
		||||
  --el-mask-color: rgba(255, 255, 255, 0.5);
 | 
			
		||||
  --van-toast-background: rgba(255, 255, 255, 0.3);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,8 @@
 | 
			
		||||
  // 操作按钮
 | 
			
		||||
  --btn-bg: rgba(100, 100, 100, .1);
 | 
			
		||||
 | 
			
		||||
  // 加载动画
 | 
			
		||||
  --el-mask-color: rgba(100, 100, 100, 0.2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,18 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="page-apps custom-scroll">
 | 
			
		||||
      <div class="apps-type-nav">
 | 
			
		||||
        <el-scrollbar>
 | 
			
		||||
          <ul class="scrollbar-type-nav">
 | 
			
		||||
            <li :class="{ active: typeId === '' }" @click="getAppList('')">
 | 
			
		||||
              全部分类
 | 
			
		||||
            </li>
 | 
			
		||||
            <li
 | 
			
		||||
              v-for="item in appTypes"
 | 
			
		||||
              :key="item.id"
 | 
			
		||||
              :class="{ active: typeId === item.id }"
 | 
			
		||||
              @click="getAppList(item.id)"
 | 
			
		||||
            >
 | 
			
		||||
              <div class="image" v-if="item.icon">
 | 
			
		||||
                <el-image :src="item.icon" fit="cover" />
 | 
			
		||||
              </div>
 | 
			
		||||
              {{ item.name }}
 | 
			
		||||
            </li>
 | 
			
		||||
          </ul>
 | 
			
		||||
        </el-scrollbar>
 | 
			
		||||
      <div class="flex h-20">
 | 
			
		||||
        <ul class="scrollbar-type-nav">
 | 
			
		||||
          <li :class="{ active: typeId === '' }" @click="getAppList('')">全部分类</li>
 | 
			
		||||
          <li v-for="item in appTypes" :key="item.id" :class="{ active: typeId === item.id }" @click="getAppList(item.id)">
 | 
			
		||||
            <div class="image" v-if="item.icon">
 | 
			
		||||
              <el-image :src="item.icon" fit="cover" />
 | 
			
		||||
            </div>
 | 
			
		||||
            {{ item.name }}
 | 
			
		||||
          </li>
 | 
			
		||||
        </ul>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="app-list-container" :style="{ height: listBoxHeight + 'px' }">
 | 
			
		||||
        <ItemList :items="list" v-if="list.length > 0" :gap="15" :width="300">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
@@ -35,31 +27,12 @@
 | 
			
		||||
                  <div class="info-text">{{ scope.item.hello_msg }}</div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="btn">
 | 
			
		||||
                  <el-button
 | 
			
		||||
                    size="small"
 | 
			
		||||
                    class="sm-btn-theme"
 | 
			
		||||
                    @click="useRole(scope.item)"
 | 
			
		||||
                    >使用</el-button
 | 
			
		||||
                  >
 | 
			
		||||
                  <el-tooltip
 | 
			
		||||
                    content="从工作区移除"
 | 
			
		||||
                    placement="top"
 | 
			
		||||
                    v-if="hasRole(scope.item.key)"
 | 
			
		||||
                  >
 | 
			
		||||
                    <el-button
 | 
			
		||||
                      size="small"
 | 
			
		||||
                      type="danger"
 | 
			
		||||
                      @click="updateRole(scope.item, 'remove')"
 | 
			
		||||
                      >移除</el-button
 | 
			
		||||
                    >
 | 
			
		||||
                  <el-button size="small" class="sm-btn-theme" @click="useRole(scope.item)">使用</el-button>
 | 
			
		||||
                  <el-tooltip content="从工作区移除" placement="top" v-if="hasRole(scope.item.key)">
 | 
			
		||||
                    <el-button size="small" type="danger" @click="updateRole(scope.item, 'remove')">移除</el-button>
 | 
			
		||||
                  </el-tooltip>
 | 
			
		||||
                  <el-tooltip content="添加到工作区" placement="top" v-else>
 | 
			
		||||
                    <el-button
 | 
			
		||||
                      size="small"
 | 
			
		||||
                      style="--el-color-primary: #009999"
 | 
			
		||||
                      @click="updateRole(scope.item, 'add')"
 | 
			
		||||
                      >添加</el-button
 | 
			
		||||
                    >
 | 
			
		||||
                    <el-button size="small" style="--el-color-primary: #009999" @click="updateRole(scope.item, 'add')">添加</el-button>
 | 
			
		||||
                  </el-tooltip>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
@@ -179,7 +152,7 @@ const updateRole = (row, opt) => {
 | 
			
		||||
        .then(() => {
 | 
			
		||||
          ElMessage.success({
 | 
			
		||||
            message: title.value + "成功!",
 | 
			
		||||
            duration: 1000
 | 
			
		||||
            duration: 1000,
 | 
			
		||||
          });
 | 
			
		||||
        })
 | 
			
		||||
        .catch((e) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,6 @@
 | 
			
		||||
                  ref="promptRef"
 | 
			
		||||
                  placeholder="请在此输入绘画提示词,您也可以点击下面的提示词助手生成绘画提示词"
 | 
			
		||||
                  v-loading="isGenerating"
 | 
			
		||||
                  style="--el-mask-color: rgba(100, 100, 100, 0.8)"
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -178,7 +178,6 @@
 | 
			
		||||
                        type="textarea"
 | 
			
		||||
                        ref="promptRef"
 | 
			
		||||
                        v-loading="isGenerating"
 | 
			
		||||
                        style="--el-mask-color: rgba(100, 100, 100, 0.8)"
 | 
			
		||||
                        placeholder="请在此输入绘画提示词,您也可以点击下面的提示词助手生成绘画提示词"
 | 
			
		||||
                      />
 | 
			
		||||
                    </div>
 | 
			
		||||
@@ -272,7 +271,6 @@
 | 
			
		||||
                        type="textarea"
 | 
			
		||||
                        ref="promptRef"
 | 
			
		||||
                        v-loading="isGenerating"
 | 
			
		||||
                        style="--el-mask-color: rgba(100, 100, 100, 0.8)"
 | 
			
		||||
                        placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"
 | 
			
		||||
                      />
 | 
			
		||||
                    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -196,7 +196,6 @@
 | 
			
		||||
                  ref="promptRef"
 | 
			
		||||
                  placeholder="请在此输入绘画提示词,您也可以点击下面的提示词助手生成绘画提示词"
 | 
			
		||||
                  v-loading="isGenerating"
 | 
			
		||||
                  style="--el-mask-color: rgba(100, 100, 100, 0.8)"
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,24 +15,11 @@
 | 
			
		||||
      <div class="prompt-container">
 | 
			
		||||
        <div class="input-container">
 | 
			
		||||
          <div class="upload-icon" v-if="images.length < 2">
 | 
			
		||||
            <el-upload
 | 
			
		||||
              class="avatar-uploader"
 | 
			
		||||
              :auto-upload="true"
 | 
			
		||||
              :show-file-list="false"
 | 
			
		||||
              :http-request="upload"
 | 
			
		||||
              accept=".jpg,.png,.jpeg"
 | 
			
		||||
            >
 | 
			
		||||
            <el-upload class="avatar-uploader" :auto-upload="true" :show-file-list="false" :http-request="upload" accept=".jpg,.png,.jpeg">
 | 
			
		||||
              <i class="iconfont icon-image"></i>
 | 
			
		||||
            </el-upload>
 | 
			
		||||
          </div>
 | 
			
		||||
          <textarea
 | 
			
		||||
            class="prompt-input"
 | 
			
		||||
            :rows="row"
 | 
			
		||||
            v-model="formData.prompt"
 | 
			
		||||
            placeholder="请输入提示词或者上传图片"
 | 
			
		||||
            autofocus
 | 
			
		||||
          >
 | 
			
		||||
          </textarea>
 | 
			
		||||
          <textarea class="prompt-input" :rows="row" v-model="formData.prompt" placeholder="请输入提示词或者上传图片" autofocus> </textarea>
 | 
			
		||||
          <div class="send-icon" @click="create">
 | 
			
		||||
            <i class="iconfont icon-send"></i>
 | 
			
		||||
          </div>
 | 
			
		||||
@@ -40,13 +27,7 @@
 | 
			
		||||
 | 
			
		||||
        <div class="params">
 | 
			
		||||
          <div class="item-group">
 | 
			
		||||
            <el-button
 | 
			
		||||
              class="generate-btn"
 | 
			
		||||
              size="small"
 | 
			
		||||
              @click="generatePrompt"
 | 
			
		||||
              color="#5865f2"
 | 
			
		||||
              :disabled="isGenerating"
 | 
			
		||||
            >
 | 
			
		||||
            <el-button class="generate-btn" size="small" @click="generatePrompt" color="#5865f2">
 | 
			
		||||
              <i class="iconfont icon-chuangzuo" style="margin-right: 5px"></i>
 | 
			
		||||
              <span>生成AI视频提示词</span>
 | 
			
		||||
            </el-button>
 | 
			
		||||
@@ -63,12 +44,8 @@
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <el-container
 | 
			
		||||
      class="video-container"
 | 
			
		||||
      v-loading="loading"
 | 
			
		||||
      element-loading-background="rgba(100,100,100,0.3)"
 | 
			
		||||
    >
 | 
			
		||||
      <h2 class="h-title">你的作品</h2>
 | 
			
		||||
    <el-container class="video-container" v-loading="loading" element-loading-background="rgba(100,100,100,0.3)">
 | 
			
		||||
      <h2 class="h-title text-2xl mb-5 mt-2">你的作品</h2>
 | 
			
		||||
 | 
			
		||||
      <div class="list-box" v-if="!noData">
 | 
			
		||||
        <div v-for="item in list" :key="item.id">
 | 
			
		||||
@@ -76,60 +53,30 @@
 | 
			
		||||
            <div class="left">
 | 
			
		||||
              <div class="container">
 | 
			
		||||
                <div v-if="item.progress === 100">
 | 
			
		||||
                  <video
 | 
			
		||||
                    class="video"
 | 
			
		||||
                    :src="replaceImg(item.video_url)"
 | 
			
		||||
                    preload="auto"
 | 
			
		||||
                    loop="loop"
 | 
			
		||||
                    muted="muted"
 | 
			
		||||
                  >
 | 
			
		||||
                    您的浏览器不支持视频播放
 | 
			
		||||
                  </video>
 | 
			
		||||
                  <video class="video" :src="replaceImg(item.video_url)" preload="auto" loop="loop" muted="muted">您的浏览器不支持视频播放</video>
 | 
			
		||||
                  <button class="play" @click="play(item)">
 | 
			
		||||
                    <img src="/images/play.svg" alt="" />
 | 
			
		||||
                  </button>
 | 
			
		||||
                </div>
 | 
			
		||||
                <el-image
 | 
			
		||||
                  :src="item.cover_url"
 | 
			
		||||
                  fit="cover"
 | 
			
		||||
                  v-else-if="item.progress > 100"
 | 
			
		||||
                />
 | 
			
		||||
                <el-image :src="item.cover_url" fit="cover" v-else-if="item.progress > 100" />
 | 
			
		||||
                <generating message="正在生成视频" v-else />
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="center">
 | 
			
		||||
              <div class="failed" v-if="item.progress === 101">
 | 
			
		||||
                任务执行失败:{{ item.err_msg }},任务提示词:{{ item.prompt }}
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="failed" v-if="item.progress === 101">任务执行失败:{{ item.err_msg }},任务提示词:{{ item.prompt }}</div>
 | 
			
		||||
              <div class="prompt" v-else>{{ item.prompt }}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="right" v-if="item.progress === 100">
 | 
			
		||||
              <div class="tools">
 | 
			
		||||
                <button class="btn btn-publish">
 | 
			
		||||
                  <span class="text">发布</span>
 | 
			
		||||
                  <black-switch
 | 
			
		||||
                    v-model:value="item.publish"
 | 
			
		||||
                    @change="publishJob(item)"
 | 
			
		||||
                    size="small"
 | 
			
		||||
                  />
 | 
			
		||||
                  <black-switch v-model:value="item.publish" @change="publishJob(item)" size="small" />
 | 
			
		||||
                </button>
 | 
			
		||||
 | 
			
		||||
                <el-tooltip content="下载视频" placement="top">
 | 
			
		||||
                  <button
 | 
			
		||||
                    class="btn btn-icon"
 | 
			
		||||
                    @click="download(item)"
 | 
			
		||||
                    :disabled="item.downloading"
 | 
			
		||||
                  >
 | 
			
		||||
                    <i
 | 
			
		||||
                      class="iconfont icon-download"
 | 
			
		||||
                      v-if="!item.downloading"
 | 
			
		||||
                    ></i>
 | 
			
		||||
                    <el-image
 | 
			
		||||
                      src="/images/loading.gif"
 | 
			
		||||
                      class="downloading"
 | 
			
		||||
                      fit="cover"
 | 
			
		||||
                      v-else
 | 
			
		||||
                    />
 | 
			
		||||
                  <button class="btn btn-icon" @click="download(item)" :disabled="item.downloading">
 | 
			
		||||
                    <i class="iconfont icon-download" v-if="!item.downloading"></i>
 | 
			
		||||
                    <el-image src="/images/loading.gif" class="downloading" fit="cover" v-else />
 | 
			
		||||
                  </button>
 | 
			
		||||
                </el-tooltip>
 | 
			
		||||
                <el-tooltip content="删除" placement="top">
 | 
			
		||||
@@ -147,12 +94,7 @@
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-empty
 | 
			
		||||
        :image-size="100"
 | 
			
		||||
        :image="nodata"
 | 
			
		||||
        description="没有任何作品,赶紧去创作吧!"
 | 
			
		||||
        v-else
 | 
			
		||||
      />
 | 
			
		||||
      <el-empty :image-size="100" :image="nodata" description="没有任何作品,赶紧去创作吧!" v-else />
 | 
			
		||||
 | 
			
		||||
      <div class="pagination">
 | 
			
		||||
        <el-pagination
 | 
			
		||||
@@ -168,22 +110,8 @@
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-container>
 | 
			
		||||
    <black-dialog
 | 
			
		||||
      v-model:show="showDialog"
 | 
			
		||||
      title="预览视频"
 | 
			
		||||
      hide-footer
 | 
			
		||||
      @cancal="showDialog = false"
 | 
			
		||||
      width="auto"
 | 
			
		||||
    >
 | 
			
		||||
      <video
 | 
			
		||||
        style="width: 100%; max-height: 90vh"
 | 
			
		||||
        :src="currentVideoUrl"
 | 
			
		||||
        preload="auto"
 | 
			
		||||
        :autoplay="true"
 | 
			
		||||
        loop="loop"
 | 
			
		||||
        muted="muted"
 | 
			
		||||
        v-show="showDialog"
 | 
			
		||||
      >
 | 
			
		||||
    <black-dialog v-model:show="showDialog" title="预览视频" hide-footer @cancal="showDialog = false" width="auto">
 | 
			
		||||
      <video style="width: 100%; max-height: 90vh" :src="currentVideoUrl" preload="auto" :autoplay="true" loop="loop" muted="muted" v-show="showDialog">
 | 
			
		||||
        您的浏览器不支持视频播放
 | 
			
		||||
      </video>
 | 
			
		||||
    </black-dialog>
 | 
			
		||||
@@ -197,7 +125,7 @@ import { onMounted, onUnmounted, reactive, ref } from "vue";
 | 
			
		||||
import { CircleCloseFilled } from "@element-plus/icons-vue";
 | 
			
		||||
import { httpDownload, httpPost, httpGet } from "@/utils/http";
 | 
			
		||||
import { checkSession, getClientId } from "@/store/cache";
 | 
			
		||||
import { showMessageError, showMessageOK } from "@/utils/dialog";
 | 
			
		||||
import { closeLoading, showLoading, showMessageError, showMessageOK } from "@/utils/dialog";
 | 
			
		||||
import { replaceImg } from "@/utils/libs";
 | 
			
		||||
import { ElMessage, ElMessageBox } from "element-plus";
 | 
			
		||||
import BlackSwitch from "@/components/ui/BlackSwitch.vue";
 | 
			
		||||
@@ -216,7 +144,7 @@ const formData = reactive({
 | 
			
		||||
  expand_prompt: false,
 | 
			
		||||
  loop: false,
 | 
			
		||||
  first_frame_img: "",
 | 
			
		||||
  end_frame_img: ""
 | 
			
		||||
  end_frame_img: "",
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
@@ -275,7 +203,7 @@ const removeJob = (item) => {
 | 
			
		||||
  ElMessageBox.confirm("此操作将会删除任务相关文件,继续操作码?", "删除提示", {
 | 
			
		||||
    confirmButtonText: "确认",
 | 
			
		||||
    cancelButtonText: "取消",
 | 
			
		||||
    type: "warning"
 | 
			
		||||
    type: "warning",
 | 
			
		||||
  })
 | 
			
		||||
    .then(() => {
 | 
			
		||||
      httpGet("/api/video/remove", { id: item.id })
 | 
			
		||||
@@ -334,7 +262,7 @@ const fetchData = (_page) => {
 | 
			
		||||
  httpGet("/api/video/list", {
 | 
			
		||||
    page: page.value,
 | 
			
		||||
    page_size: pageSize.value,
 | 
			
		||||
    type: "luma"
 | 
			
		||||
    type: "luma",
 | 
			
		||||
  })
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      total.value = res.data.total;
 | 
			
		||||
@@ -368,20 +296,19 @@ const create = () => {
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const isGenerating = ref(false);
 | 
			
		||||
const generatePrompt = () => {
 | 
			
		||||
  if (formData.prompt === "") {
 | 
			
		||||
    return showMessageError("请输入原始提示词");
 | 
			
		||||
  }
 | 
			
		||||
  isGenerating.value = true;
 | 
			
		||||
  httpPost("/api/prompt/image", { prompt: formData.prompt })
 | 
			
		||||
  showLoading("正在生成视频脚本...");
 | 
			
		||||
  httpPost("/api/prompt/video", { prompt: formData.prompt })
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      formData.prompt = res.data;
 | 
			
		||||
      isGenerating.value = false;
 | 
			
		||||
      closeLoading();
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      showMessageError("生成提示词失败:" + e.message);
 | 
			
		||||
      isGenerating.value = false;
 | 
			
		||||
      closeLoading();
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-popover>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="item" v-loading="isGenerating" element-loading-text="正在生成歌词..." element-loading-background="rgba(122, 122, 122, 0.8)">
 | 
			
		||||
            <div class="item" v-loading="isGenerating" element-loading-text="正在生成歌词...">
 | 
			
		||||
              <black-input v-model:value="data.lyrics" type="textarea" :rows="10" :placeholder="promptPlaceholder" />
 | 
			
		||||
              <button class="btn btn-lyric" @click="createLyric">生成歌词</button>
 | 
			
		||||
            </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="system-config form" v-loading="loading">
 | 
			
		||||
 | 
			
		||||
    <el-tabs v-model="activeName" class="sys-tabs">
 | 
			
		||||
      <el-tab-pane label="系统配置" name="basic">
 | 
			
		||||
        <div class="container">
 | 
			
		||||
@@ -8,25 +7,20 @@
 | 
			
		||||
            <el-tabs type="border-card">
 | 
			
		||||
              <el-tab-pane label="基础配置">
 | 
			
		||||
                <el-form-item label="网站标题" prop="title">
 | 
			
		||||
                  <el-input v-model="system['title']"/>
 | 
			
		||||
                  <el-input v-model="system['title']" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="控制台标题" prop="admin_title">
 | 
			
		||||
                  <el-input v-model="system['admin_title']"/>
 | 
			
		||||
                  <el-input v-model="system['admin_title']" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="网站Slogan" prop="slogan">
 | 
			
		||||
                  <el-input v-model="system['slogan']"/>
 | 
			
		||||
                  <el-input v-model="system['slogan']" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="网站 LOGO" prop="logo">
 | 
			
		||||
                  <el-input v-model="system['logo']" placeholder="网站LOGO图片">
 | 
			
		||||
                    <template #append>
 | 
			
		||||
                      <el-upload
 | 
			
		||||
                          :auto-upload="true"
 | 
			
		||||
                          :show-file-list="false"
 | 
			
		||||
                          @click="beforeUpload('logo')"
 | 
			
		||||
                          :http-request="uploadImg"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-upload :auto-upload="true" :show-file-list="false" @click="beforeUpload('logo')" :http-request="uploadImg">
 | 
			
		||||
                        <el-icon class="uploader-icon">
 | 
			
		||||
                          <UploadFilled/>
 | 
			
		||||
                          <UploadFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-upload>
 | 
			
		||||
                    </template>
 | 
			
		||||
@@ -37,14 +31,9 @@
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      首页背景图
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="网站首页背景图片"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="网站首页背景图片" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
@@ -52,14 +41,9 @@
 | 
			
		||||
                  <div class="d-flex justify-between w-100">
 | 
			
		||||
                    <el-input v-model="system['index_bg_url']" placeholder="网站首页背景图片">
 | 
			
		||||
                      <template #append>
 | 
			
		||||
                        <el-upload
 | 
			
		||||
                            :auto-upload="true"
 | 
			
		||||
                            :show-file-list="false"
 | 
			
		||||
                            @click="beforeUpload('index_bg_url')"
 | 
			
		||||
                            :http-request="uploadImg"
 | 
			
		||||
                        >
 | 
			
		||||
                        <el-upload :auto-upload="true" :show-file-list="false" @click="beforeUpload('index_bg_url')" :http-request="uploadImg">
 | 
			
		||||
                          <el-icon class="uploader-icon">
 | 
			
		||||
                            <UploadFilled/>
 | 
			
		||||
                            <UploadFilled />
 | 
			
		||||
                          </el-icon>
 | 
			
		||||
                        </el-upload>
 | 
			
		||||
                      </template>
 | 
			
		||||
@@ -73,55 +57,34 @@
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      首页导航菜单
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="被选中的菜单将会在首页导航栏显示"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="被选中的菜单将会在首页导航栏显示" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-select
 | 
			
		||||
                        v-model="system['index_navs']"
 | 
			
		||||
                        multiple
 | 
			
		||||
                        :filterable="true"
 | 
			
		||||
                        placeholder="请选择菜单,多选"
 | 
			
		||||
                        style="width: 100%"
 | 
			
		||||
                    >
 | 
			
		||||
                      <el-option
 | 
			
		||||
                          v-for="item in menus"
 | 
			
		||||
                          :key="item.id"
 | 
			
		||||
                          :label="item.name"
 | 
			
		||||
                          :value="item.id"
 | 
			
		||||
                      />
 | 
			
		||||
                    </el-select>
 | 
			
		||||
                  <el-select v-model="system['index_navs']" multiple :filterable="true" placeholder="请选择菜单,多选" style="width: 100%">
 | 
			
		||||
                    <el-option v-for="item in menus" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
                  </el-select>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item label="版权信息" prop="copyright">
 | 
			
		||||
                  <el-input v-model="system['copyright']" placeholder="更改此选项需要获取 License 授权"/>
 | 
			
		||||
                  <el-input v-model="system['copyright']" placeholder="更改此选项需要获取 License 授权" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      开放注册
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="关闭注册之后只能通过管理后台添加用户"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="关闭注册之后只能通过管理后台添加用户" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-switch v-model="system['enabled_register']"/>
 | 
			
		||||
                  <el-switch v-model="system['enabled_register']" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
@@ -129,18 +92,18 @@
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      启用验证码
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="启用验证码之后,注册登录都会加载行为验证码,增加安全性。此功能需要购买验证码服务才会生效。"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                        effect="dark"
 | 
			
		||||
                        content="启用验证码之后,注册登录都会加载行为验证码,增加安全性。此功能需要购买验证码服务才会生效。"
 | 
			
		||||
                        raw-content
 | 
			
		||||
                        placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-switch v-model="system['enabled_verify']"/>
 | 
			
		||||
                  <el-switch v-model="system['enabled_verify']" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item label="注册方式" prop="register_ways">
 | 
			
		||||
@@ -152,20 +115,15 @@
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item label="邮件域名白名单" prop="register_ways">
 | 
			
		||||
                  <items-input v-model:value="system['email_white_list']"/>
 | 
			
		||||
                  <items-input v-model:value="system['email_white_list']" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item label="微信客服二维码" prop="wechat_card_url">
 | 
			
		||||
                  <el-input v-model="system['wechat_card_url']" placeholder="微信客服二维码">
 | 
			
		||||
                    <template #append>
 | 
			
		||||
                      <el-upload
 | 
			
		||||
                          :auto-upload="true"
 | 
			
		||||
                          :show-file-list="false"
 | 
			
		||||
                          @click="beforeUpload('wechat_card_url')"
 | 
			
		||||
                          :http-request="uploadImg"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-upload :auto-upload="true" :show-file-list="false" @click="beforeUpload('wechat_card_url')" :http-request="uploadImg">
 | 
			
		||||
                        <el-icon class="uploader-icon">
 | 
			
		||||
                          <UploadFilled/>
 | 
			
		||||
                          <UploadFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-upload>
 | 
			
		||||
                    </template>
 | 
			
		||||
@@ -175,41 +133,26 @@
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      默认翻译模型
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="选择一个默认模型来翻译提示词"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="选择一个默认模型来翻译提示词" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-select
 | 
			
		||||
                          v-model.number="system['translate_model_id']"
 | 
			
		||||
                          :filterable="true"
 | 
			
		||||
                          placeholder="选择一个默认模型来翻译提示词"
 | 
			
		||||
                          style="width: 100%"
 | 
			
		||||
                      >
 | 
			
		||||
                    <el-option
 | 
			
		||||
                        v-for="item in models"
 | 
			
		||||
                        :key="item.id"
 | 
			
		||||
                        :label="item.name"
 | 
			
		||||
                        :value="item.id"
 | 
			
		||||
                    />
 | 
			
		||||
                  <el-select v-model.number="system['translate_model_id']" :filterable="true" placeholder="选择一个默认模型来翻译提示词" style="width: 100%">
 | 
			
		||||
                    <el-option v-for="item in models" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
                  </el-select>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item label="开启聊天上下文">
 | 
			
		||||
                  <el-switch v-model="system['enable_context']"/>
 | 
			
		||||
                  <el-switch v-model="system['enable_context']" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="会话上下文深度">
 | 
			
		||||
                  <div class="tip-input-line">
 | 
			
		||||
                    <el-input-number v-model="system['context_deep']" :min="0" :max="10"/>
 | 
			
		||||
                    <div class="tip">会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为
 | 
			
		||||
                      0
 | 
			
		||||
                    <el-input-number v-model="system['context_deep']" :min="0" :max="10" />
 | 
			
		||||
                    <div class="tip">
 | 
			
		||||
                      会话上下文深度:在老会话中继续会话,默认加载多少条聊天记录作为上下文。如果设置为 0
 | 
			
		||||
                      则不加载聊天记录,仅仅使用当前角色的上下文。该配置参数必须设置需要为偶数。
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
@@ -219,62 +162,49 @@
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      SD反向提示词
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="Stable-Diffusion 绘画默认反向提示词"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="Stable-Diffusion 绘画默认反向提示词" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-input type="textarea" :rows="2" v-model="system['sd_neg_prompt']" placeholder=""/>
 | 
			
		||||
                  <el-input type="textarea" :rows="2" v-model="system['sd_neg_prompt']" placeholder="" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item label="会员充值说明" prop="order_pay_timeout">
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      会员充值说明
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="会员充值页面的充值说明文字"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="会员充值页面的充值说明文字" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-input type="textarea" :rows="2" v-model="system['vip_info_text']" placeholder=""/>
 | 
			
		||||
                  <el-input type="textarea" :rows="2" v-model="system['vip_info_text']" placeholder="" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item label="MJ默认API模式" prop="mj_mode">
 | 
			
		||||
                  <el-select v-model="system['mj_mode']" placeholder="请选择模式">
 | 
			
		||||
                    <el-option v-for="item in mjModels" :value="item.value" :label="item.name" :key="item.value">{{
 | 
			
		||||
                        item.name
 | 
			
		||||
                      }}
 | 
			
		||||
                    </el-option>
 | 
			
		||||
                    <el-option v-for="item in mjModels" :value="item.value" :label="item.name" :key="item.value">{{ item.name }} </el-option>
 | 
			
		||||
                  </el-select>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
              <el-tab-pane label="算力配置">
 | 
			
		||||
                <el-form-item label="注册赠送算力" prop="init_power">
 | 
			
		||||
                  <el-input v-model.number="system['init_power']" placeholder="新用户注册赠送算力"/>
 | 
			
		||||
                  <el-input v-model.number="system['init_power']" placeholder="新用户注册赠送算力" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="邀请赠送算力" prop="invite_power">
 | 
			
		||||
                  <el-input v-model.number="system['invite_power']" placeholder="邀请新用户注册赠送算力"/>
 | 
			
		||||
                  <el-input v-model.number="system['invite_power']" placeholder="邀请新用户注册赠送算力" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="VIP每月赠送算力" prop="vip_month_power">
 | 
			
		||||
                  <el-input v-model.number="system['vip_month_power']" placeholder="VIP用户每月赠送算力"/>
 | 
			
		||||
                  <el-input v-model.number="system['vip_month_power']" placeholder="VIP用户每月赠送算力" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="每日赠送算力" prop="daily_power">
 | 
			
		||||
                    <el-input v-model.number="system['daily_power']" placeholder="默认值0"/>
 | 
			
		||||
                  <el-input v-model.number="system['daily_power']" placeholder="默认值0" />
 | 
			
		||||
 | 
			
		||||
                  <el-text type="info">
 | 
			
		||||
                    如果设置0表示不赠送,用户享受完免费算力额度之后就不能再发起对话了。如果设置为N,则系统每天将算力值小于N的用户自动补充到N。注意,此功能要配合XXL-JOB启用。
 | 
			
		||||
@@ -284,72 +214,70 @@
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      MJ绘图算力
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="使用MidJourney画一张图消耗算力"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="使用MidJourney画一张图消耗算力" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-input v-model.number="system['mj_power']" placeholder=""/>
 | 
			
		||||
                  <el-input v-model.number="system['mj_power']" placeholder="" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      MJ操作算力
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="放大,变换,重绘操作一次消耗的算力"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="放大,变换,重绘操作一次消耗的算力" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-input v-model.number="system['mj_action_power']" placeholder=""/>
 | 
			
		||||
                  <el-input v-model.number="system['mj_action_power']" placeholder="" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="Stable-Diffusion算力" prop="sd_power">
 | 
			
		||||
                  <el-input v-model.number="system['sd_power']" placeholder="使用Stable-Diffusion画一张图消耗算力"/>
 | 
			
		||||
                  <el-input v-model.number="system['sd_power']" placeholder="使用Stable-Diffusion画一张图消耗算力" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="DALL-E-3算力" prop="dall_power">
 | 
			
		||||
                  <el-input v-model.number="system['dall_power']" placeholder="使用DALL-E-3画一张图消耗算力"/>
 | 
			
		||||
                  <el-input v-model.number="system['dall_power']" placeholder="使用DALL-E-3画一张图消耗算力" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="Suno 算力" prop="suno_power">
 | 
			
		||||
                  <el-input v-model.number="system['suno_power']" placeholder="使用 Suno 生成一首音乐消耗算力"/>
 | 
			
		||||
                  <el-input v-model.number="system['suno_power']" placeholder="使用 Suno 生成一首音乐消耗算力" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="Luma 算力" prop="luma_power">
 | 
			
		||||
                  <el-input v-model.number="system['luma_power']" placeholder="使用 Luma 生成一段视频消耗算力"/>
 | 
			
		||||
                  <el-input v-model.number="system['luma_power']" placeholder="使用 Luma 生成一段视频消耗算力" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
                  <template #label>
 | 
			
		||||
                    <div class="label-title">
 | 
			
		||||
                      高级语音算力
 | 
			
		||||
                      <el-tooltip
 | 
			
		||||
                          effect="dark"
 | 
			
		||||
                          content="使用一次 OpenAI 高级语音对话消耗的算力"
 | 
			
		||||
                          raw-content
 | 
			
		||||
                          placement="right"
 | 
			
		||||
                      >
 | 
			
		||||
                      <el-tooltip effect="dark" content="使用一次 OpenAI 高级语音对话消耗的算力" raw-content placement="right">
 | 
			
		||||
                        <el-icon>
 | 
			
		||||
                          <InfoFilled/>
 | 
			
		||||
                          <InfoFilled />
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                      </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                  <el-input v-model.number="system['advance_voice_power']" placeholder=""/>
 | 
			
		||||
                  <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>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
            </el-tabs>
 | 
			
		||||
 | 
			
		||||
            <div style="padding: 10px;">
 | 
			
		||||
            <div style="padding: 10px">
 | 
			
		||||
              <el-form-item>
 | 
			
		||||
                <el-button type="primary" @click="save('system')">保存</el-button>
 | 
			
		||||
              </el-form-item>
 | 
			
		||||
@@ -358,34 +286,28 @@
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="公告配置" name="notice">
 | 
			
		||||
        <md-editor class="mgb20" v-model="notice" :theme="store.theme" @on-upload-img="onUploadImg"/>
 | 
			
		||||
        <md-editor class="mgb20" v-model="notice" :theme="store.theme" @on-upload-img="onUploadImg" />
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <div style="padding-top: 10px;margin-left: 150px;">
 | 
			
		||||
          <div style="padding-top: 10px; margin-left: 150px">
 | 
			
		||||
            <el-button type="primary" @click="save('notice')">保存</el-button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="思维导图" name="mark_map">
 | 
			
		||||
        <md-editor class="mgb20" :theme="store.theme" v-model="system['mark_map_text']" @on-upload-img="onUploadImg"/>
 | 
			
		||||
        <md-editor class="mgb20" :theme="store.theme" v-model="system['mark_map_text']" @on-upload-img="onUploadImg" />
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <div style="padding-top: 10px;margin-left: 150px;">
 | 
			
		||||
          <div style="padding-top: 10px; margin-left: 150px">
 | 
			
		||||
            <el-button type="primary" @click="save('system')">保存</el-button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="菜单配置" name="menu">
 | 
			
		||||
        <Menu/>
 | 
			
		||||
        <Menu />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="授权激活" name="license">
 | 
			
		||||
        <div class="container">
 | 
			
		||||
          <el-descriptions
 | 
			
		||||
              v-if="license.is_active"
 | 
			
		||||
              class="margin-top"
 | 
			
		||||
              title="已授权信息"
 | 
			
		||||
              :column="1"
 | 
			
		||||
              border
 | 
			
		||||
          >
 | 
			
		||||
          <el-descriptions v-if="license.is_active" class="margin-top" title="已授权信息" :column="1" border>
 | 
			
		||||
            <el-descriptions-item>
 | 
			
		||||
              <template #label>
 | 
			
		||||
                <div class="cell-item">License Key</div>
 | 
			
		||||
@@ -428,7 +350,7 @@
 | 
			
		||||
 | 
			
		||||
          <el-form :model="system" label-width="150px" label-position="right">
 | 
			
		||||
            <el-form-item label="许可授权码" prop="license">
 | 
			
		||||
              <el-input v-model="licenseKey"/>
 | 
			
		||||
              <el-input v-model="licenseKey" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
 | 
			
		||||
            <el-form-item>
 | 
			
		||||
@@ -440,12 +362,14 @@
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="修复数据" name="fixData">
 | 
			
		||||
        <div class="container">
 | 
			
		||||
          <p class="text">有些版本升级的时候更新了数据库的结构,比如字段名字改了,需要把之前的字段的值转移到其他字段,这些无法通过简单的
 | 
			
		||||
            SQL 语句可以实现的,需要手动写程序修正数据。</p>
 | 
			
		||||
          <p class="text">
 | 
			
		||||
            有些版本升级的时候更新了数据库的结构,比如字段名字改了,需要把之前的字段的值转移到其他字段,这些无法通过简单的 SQL
 | 
			
		||||
            语句可以实现的,需要手动写程序修正数据。
 | 
			
		||||
          </p>
 | 
			
		||||
 | 
			
		||||
<!--          <p class="text">当前版本 v4.1.4 需要修正用户数据,增加了 mobile 和 email 字段,需要把之前用手机号或者邮箱注册的用户的 username 字段数据初始化到 mobile 或者 email 字段。另外,需要把订单的支付渠道从名字称修正为 key。</p>-->
 | 
			
		||||
          <!--          <p class="text">当前版本 v4.1.4 需要修正用户数据,增加了 mobile 和 email 字段,需要把之前用手机号或者邮箱注册的用户的 username 字段数据初始化到 mobile 或者 email 字段。另外,需要把订单的支付渠道从名字称修正为 key。</p>-->
 | 
			
		||||
 | 
			
		||||
<!--          <el-text type="danger">请注意:在修复数据前,请先备份好数据库,以免数据丢失!</el-text>-->
 | 
			
		||||
          <!--          <el-text type="danger">请注意:在修复数据前,请先备份好数据库,以免数据丢失!</el-text>-->
 | 
			
		||||
 | 
			
		||||
          <p><el-button type="primary" @click="fixData">立即修复</el-button></p>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -455,117 +379,133 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {onMounted, reactive, ref} from "vue";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import { onMounted, reactive, ref } from "vue";
 | 
			
		||||
import { httpGet, httpPost } from "@/utils/http";
 | 
			
		||||
import Compressor from "compressorjs";
 | 
			
		||||
import {ElMessage, ElMessageBox} from "element-plus";
 | 
			
		||||
import {CloseBold, InfoFilled, Select, UploadFilled} from "@element-plus/icons-vue";
 | 
			
		||||
import { ElMessage, ElMessageBox } from "element-plus";
 | 
			
		||||
import { CloseBold, InfoFilled, Select, UploadFilled } from "@element-plus/icons-vue";
 | 
			
		||||
import MdEditor from "md-editor-v3";
 | 
			
		||||
import 'md-editor-v3/lib/style.css';
 | 
			
		||||
import "md-editor-v3/lib/style.css";
 | 
			
		||||
import Menu from "@/views/admin/Menu.vue";
 | 
			
		||||
import {copyObj, dateFormat} from "@/utils/libs";
 | 
			
		||||
import { copyObj, dateFormat } from "@/utils/libs";
 | 
			
		||||
import ItemsInput from "@/components/ui/ItemsInput.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
import { useSharedStore } from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const activeName = ref('basic')
 | 
			
		||||
const system = ref({models: []})
 | 
			
		||||
const configBak = ref({})
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const systemFormRef = ref(null)
 | 
			
		||||
const models = ref([])
 | 
			
		||||
const notice = ref("")
 | 
			
		||||
const license = ref({is_active: false})
 | 
			
		||||
const menus = ref([])
 | 
			
		||||
const activeName = ref("basic");
 | 
			
		||||
const system = ref({ models: [] });
 | 
			
		||||
const configBak = ref({});
 | 
			
		||||
const loading = ref(true);
 | 
			
		||||
const systemFormRef = ref(null);
 | 
			
		||||
const models = ref([]);
 | 
			
		||||
const notice = ref("");
 | 
			
		||||
const license = ref({ is_active: false });
 | 
			
		||||
const menus = ref([]);
 | 
			
		||||
const mjModels = ref([
 | 
			
		||||
  {name: "慢速(Relax)", value: "relax"},
 | 
			
		||||
  {name: "快速(Fast)", value: "fast"},
 | 
			
		||||
  {name: "急速(Turbo)", value: "turbo"},
 | 
			
		||||
])
 | 
			
		||||
const store = useSharedStore()
 | 
			
		||||
  { name: "慢速(Relax)", value: "relax" },
 | 
			
		||||
  { name: "快速(Fast)", value: "fast" },
 | 
			
		||||
  { name: "急速(Turbo)", value: "turbo" },
 | 
			
		||||
]);
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  // 加载系统配置
 | 
			
		||||
  httpGet('/api/admin/config/get?key=system').then(res => {
 | 
			
		||||
    system.value = res.data
 | 
			
		||||
    configBak.value = copyObj(system.value)
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("加载系统配置失败: " + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  httpGet("/api/admin/config/get?key=system")
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      system.value = res.data;
 | 
			
		||||
      configBak.value = copyObj(system.value);
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("加载系统配置失败: " + e.message);
 | 
			
		||||
    });
 | 
			
		||||
  // 加载聊天配置
 | 
			
		||||
  httpGet('/api/admin/config/get?key=notice').then(res => {
 | 
			
		||||
    notice.value = res.data['content']
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("公告信息失败: " + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  httpGet("/api/admin/config/get?key=notice")
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      notice.value = res.data["content"];
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("公告信息失败: " + e.message);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  httpGet('/api/admin/model/list').then(res => {
 | 
			
		||||
    models.value = res.data
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取模型失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  httpGet("/api/admin/model/list")
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      models.value = res.data;
 | 
			
		||||
      loading.value = false;
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("获取模型失败:" + e.message);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  httpGet('/api/admin/menu/list').then(res => {
 | 
			
		||||
    menus.value = res.data
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取模型失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  httpGet("/api/admin/menu/list")
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      menus.value = res.data;
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("获取模型失败:" + e.message);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  fetchLicense()
 | 
			
		||||
})
 | 
			
		||||
  fetchLicense();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const fetchLicense = () => {
 | 
			
		||||
  httpGet("/api/admin/config/license").then(res => {
 | 
			
		||||
    license.value = res.data
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取 License 失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  httpGet("/api/admin/config/license")
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      license.value = res.data;
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("获取 License 失败:" + e.message);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const rules = reactive({
 | 
			
		||||
  title: [{required: true, message: '请输入网站标题', trigger: 'blur',}],
 | 
			
		||||
  admin_title: [{required: true, message: '请输入控制台标题', trigger: 'blur',}],
 | 
			
		||||
  init_chat_calls: [{required: true, message: '请输入赠送对话次数', trigger: 'blur'}],
 | 
			
		||||
  user_img_calls: [{required: true, message: '请输入赠送绘图次数', trigger: 'blur'}],
 | 
			
		||||
})
 | 
			
		||||
  title: [{ required: true, message: "请输入网站标题", trigger: "blur" }],
 | 
			
		||||
  admin_title: [{ required: true, message: "请输入控制台标题", trigger: "blur" }],
 | 
			
		||||
  init_chat_calls: [{ required: true, message: "请输入赠送对话次数", trigger: "blur" }],
 | 
			
		||||
  user_img_calls: [{ required: true, message: "请输入赠送绘图次数", trigger: "blur" }],
 | 
			
		||||
});
 | 
			
		||||
const save = function (key) {
 | 
			
		||||
  if (key === 'system') {
 | 
			
		||||
  if (key === "system") {
 | 
			
		||||
    systemFormRef.value.validate((valid) => {
 | 
			
		||||
      if (valid) {
 | 
			
		||||
        httpPost('/api/admin/config/update', {key: key, config: system.value, config_bak: configBak.value}).then(() => {
 | 
			
		||||
          ElMessage.success("操作成功!")
 | 
			
		||||
        }).catch(e => {
 | 
			
		||||
          ElMessage.error("操作失败:" + e.message)
 | 
			
		||||
        })
 | 
			
		||||
        httpPost("/api/admin/config/update", { key: key, config: system.value, config_bak: configBak.value })
 | 
			
		||||
          .then(() => {
 | 
			
		||||
            ElMessage.success("操作成功!");
 | 
			
		||||
          })
 | 
			
		||||
          .catch((e) => {
 | 
			
		||||
            ElMessage.error("操作失败:" + e.message);
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  } else if (key === 'notice') {
 | 
			
		||||
    httpPost('/api/admin/config/update', {key: key, config: {content: notice.value, updated: true}}).then(() => {
 | 
			
		||||
      ElMessage.success("操作成功!")
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("操作失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
    });
 | 
			
		||||
  } else if (key === "notice") {
 | 
			
		||||
    httpPost("/api/admin/config/update", { key: key, config: { content: notice.value, updated: true } })
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        ElMessage.success("操作成功!");
 | 
			
		||||
      })
 | 
			
		||||
      .catch((e) => {
 | 
			
		||||
        ElMessage.error("操作失败:" + e.message);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 激活授权
 | 
			
		||||
const licenseKey = ref("")
 | 
			
		||||
const licenseKey = ref("");
 | 
			
		||||
const active = () => {
 | 
			
		||||
  if (licenseKey.value === "") {
 | 
			
		||||
    return ElMessage.error("请输入授权码")
 | 
			
		||||
    return ElMessage.error("请输入授权码");
 | 
			
		||||
  }
 | 
			
		||||
  httpPost("/api/admin/config/active", {license: licenseKey.value}).then(res => {
 | 
			
		||||
    ElMessage.success("授权成功,机器编码为:" + res.data)
 | 
			
		||||
    fetchLicense()
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error(e.message)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  httpPost("/api/admin/config/active", { license: licenseKey.value })
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      ElMessage.success("授权成功,机器编码为:" + res.data);
 | 
			
		||||
      fetchLicense();
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error(e.message);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const configKey = ref("")
 | 
			
		||||
const configKey = ref("");
 | 
			
		||||
const beforeUpload = (key) => {
 | 
			
		||||
  configKey.value = key
 | 
			
		||||
}
 | 
			
		||||
  configKey.value = key;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 图片上传
 | 
			
		||||
const uploadImg = (file) => {
 | 
			
		||||
@@ -574,17 +514,19 @@ const uploadImg = (file) => {
 | 
			
		||||
    quality: 0.6,
 | 
			
		||||
    success(result) {
 | 
			
		||||
      const formData = new FormData();
 | 
			
		||||
      formData.append('file', result, result.name);
 | 
			
		||||
      formData.append("file", result, result.name);
 | 
			
		||||
      // 执行上传操作
 | 
			
		||||
      httpPost('/api/admin/upload', formData).then((res) => {
 | 
			
		||||
        system.value[configKey.value] = res.data.url
 | 
			
		||||
        ElMessage.success('上传成功')
 | 
			
		||||
      }).catch((e) => {
 | 
			
		||||
        ElMessage.error('上传失败:' + e.message)
 | 
			
		||||
      })
 | 
			
		||||
      httpPost("/api/admin/upload", formData)
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          system.value[configKey.value] = res.data.url;
 | 
			
		||||
          ElMessage.success("上传成功");
 | 
			
		||||
        })
 | 
			
		||||
        .catch((e) => {
 | 
			
		||||
          ElMessage.error("上传失败:" + e.message);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    error(e) {
 | 
			
		||||
      ElMessage.error('上传失败:' + e.message)
 | 
			
		||||
      ElMessage.error("上传失败:" + e.message);
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
@@ -592,45 +534,44 @@ const uploadImg = (file) => {
 | 
			
		||||
// 编辑期文件上传处理
 | 
			
		||||
const onUploadImg = (files, callback) => {
 | 
			
		||||
  Promise.all(
 | 
			
		||||
      files.map((file) => {
 | 
			
		||||
        return new Promise((rev, rej) => {
 | 
			
		||||
          const formData = new FormData();
 | 
			
		||||
          formData.append('file', file, file.name);
 | 
			
		||||
          // 执行上传操作
 | 
			
		||||
          httpPost('/api/admin/upload', formData).then((res) => rev(res)).catch((error) => rej(error));
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
  ).then(res => {
 | 
			
		||||
    ElMessage.success({message: "上传成功", duration: 500})
 | 
			
		||||
    callback(res.map((item) => item.data.url));
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error('图片上传失败:' + e.message)
 | 
			
		||||
  })
 | 
			
		||||
    files.map((file) => {
 | 
			
		||||
      return new Promise((rev, rej) => {
 | 
			
		||||
        const formData = new FormData();
 | 
			
		||||
        formData.append("file", file, file.name);
 | 
			
		||||
        // 执行上传操作
 | 
			
		||||
        httpPost("/api/admin/upload", formData)
 | 
			
		||||
          .then((res) => rev(res))
 | 
			
		||||
          .catch((error) => rej(error));
 | 
			
		||||
      });
 | 
			
		||||
    })
 | 
			
		||||
  )
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      ElMessage.success({ message: "上传成功", duration: 500 });
 | 
			
		||||
      callback(res.map((item) => item.data.url));
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("图片上传失败:" + e.message);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const fixData = () => {
 | 
			
		||||
 | 
			
		||||
  ElMessageBox.confirm(
 | 
			
		||||
      '在修复数据前,请先备份好数据库,以免数据丢失!是否继续操作?',
 | 
			
		||||
      '警告',
 | 
			
		||||
      {
 | 
			
		||||
        confirmButtonText: '确定',
 | 
			
		||||
        cancelButtonText: '取消',
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
      }
 | 
			
		||||
  ).then(() => {
 | 
			
		||||
    loading.value = true
 | 
			
		||||
    httpGet("/api/admin/config/fixData").then(() => {
 | 
			
		||||
      ElMessage.success("数据修复成功")
 | 
			
		||||
      loading.value = false
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      loading.value = false
 | 
			
		||||
      ElMessage.error("数据修复失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ElMessageBox.confirm("在修复数据前,请先备份好数据库,以免数据丢失!是否继续操作?", "警告", {
 | 
			
		||||
    confirmButtonText: "确定",
 | 
			
		||||
    cancelButtonText: "取消",
 | 
			
		||||
    type: "warning",
 | 
			
		||||
  }).then(() => {
 | 
			
		||||
    loading.value = true;
 | 
			
		||||
    httpGet("/api/admin/config/fixData")
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        ElMessage.success("数据修复成功");
 | 
			
		||||
        loading.value = false;
 | 
			
		||||
      })
 | 
			
		||||
      .catch((e) => {
 | 
			
		||||
        loading.value = false;
 | 
			
		||||
        ElMessage.error("数据修复失败:" + e.message);
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus" scoped>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user