index.vue 12.9 KB
<template>
  <div class="app-container NCC-flex-main systemConfig">
    <el-form ref="baseForm" :model="baseForm" label-width="120px">
      <el-tabs v-model="activeName" type="border-card" class="NCC-el_tabs">
        <el-tab-pane label="基本设置" name="first">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="系统名称" prop="sysName">
                <el-input v-model="baseForm.sysName" clearable placeholder="系统名称" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="系统版本" prop="sysVersion">
                <el-input v-model="baseForm.sysVersion" clearable placeholder="系统版本" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="公司名称" prop="companyName">
                <el-input v-model="baseForm.companyName" clearable placeholder="公司名称" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="版权信息" prop="copyright">
                <el-input v-model="baseForm.copyright" clearable placeholder="版权信息" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="公司简称" prop="companyCode">
                <el-input v-model="baseForm.companyCode" clearable placeholder="公司简称" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="公司地址" prop="companyAddress">
                <el-input v-model="baseForm.companyAddress" clearable placeholder="公司地址" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="公司法人" prop="companyContacts">
                <el-input v-model="baseForm.companyContacts" clearable placeholder="公司法人" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="公司电话" prop="companyTelePhone">
                <el-input v-model="baseForm.companyTelePhone" clearable placeholder="公司电话" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="公司邮箱" prop="companyEmail">
                <el-input v-model="baseForm.companyEmail" clearable placeholder="公司邮箱" />
              </el-form-item>
            </el-col>
            <el-col>
              <el-form-item label="系统描述" prop="sysDescription">
                <el-input v-model="baseForm.sysDescription" type="textarea"
                  :autosize="{ minRows: 5, maxRows: 10}" placeholder="系统描述" />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" size="small" :loading="btnLoading" class="saveBtn"
                  @click="submitForm()">保 存</el-button>
              </el-form-item>
            </el-col>
          </el-row>
        </el-tab-pane>
        <el-tab-pane label="安全设置" name="second">
          <el-alert title="注意:系统登录安全、黑名单IP限制" type="warning" :closable="false" show-icon />
          <el-row>
            <el-col :span="18">
              <el-divider content-position="left">登录设置</el-divider>
              <el-form-item label="单一登录">
                <el-select v-model="baseForm.singleLogin" placeholder="请选择">
                  <el-option label="后登录踢出先登录" value="1" />
                </el-select>
              </el-form-item>
              <el-form-item label="超时登出">
                <el-input-number v-model="baseForm.tokenTimeout" :min="1" :precision="0" :step="1"
                  controls-position="right" /> 分钟
              </el-form-item>
              <el-form-item label="上次登录">
                <el-switch v-model="baseForm.lastLoginTimeSwitch" :active-value="1"
                  :inactive-value="0" />
              </el-form-item>
              <el-form-item>
                <el-card class="box-card" shadow="never" style="width: 300px;"
                  :body-style="{ padding: '0px 20px' }">
                  <div slot="header">
                    <span>上次登录信息提示</span>
                    <i style="float: right; padding: 11px 0" class="el-icon-close" />
                  </div>
                  <div class="item">
                    <p>时间:2018-10-17 12:40</p>
                    <p>地点:上海市</p>
                    <p>IP:255.255.0.0</p>
                  </div>
                </el-card>
              </el-form-item>
              <el-divider content-position="left">访问设置</el-divider>
              <el-form-item label="开启验证">
                <el-switch v-model="baseForm.whitelistSwitch" :active-value="1"
                  :inactive-value="0" />
              </el-form-item>
              <el-form-item label="允许访问IP">
                <el-input type="textarea" :autosize="{ minRows: 3, maxRows: 10}"
                  v-model="baseForm.whiteListIp" placeholder="允许访问IP" />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" size="small" :loading="btnLoading" class="saveBtn"
                  @click="submitForm()">保 存</el-button>
              </el-form-item>
            </el-col>
          </el-row>
        </el-tab-pane>
        <el-tab-pane label="AI 配置" name="third">
          <el-alert
            title="当前主推通义千问(阿里云 DashScope)。语音识别可与文本对话使用不同密钥;语音识别结果再走「文本总结」时使用下方对话配置。"
            type="info"
            :closable="false"
            show-icon
          />
          <el-row style="margin-top: 16px">
            <el-col :span="18">
              <el-divider content-position="left">语音识别</el-divider>
              <p class="form-tip">
                Paraformer<strong>异步转写(录音文件识别)</strong>专用;留空则使用官方:<code>{{ defaultParaformerSubmitUrl }}</code>。
                <strong>禁止</strong>填写下方「对话」用的 <code>compatible-mode/v1</code>,否则会提交失败。
              </p>
              <el-form-item label="语音服务地址" prop="aiSpeechApiUrl">
                <el-input
                  v-model="baseForm.aiSpeechApiUrl"
                  clearable
                  placeholder="留空即可;请勿填 compatible-mode/v1(那是对话网关)"
                />
              </el-form-item>
              <el-form-item label="语音 API Key" prop="aiSpeechApiKey">
                <el-input
                  v-model="baseForm.aiSpeechApiKey"
                  show-password
                  clearable
                  autocomplete="new-password"
                  placeholder="语音识别使用的 API Key"
                />
              </el-form-item>
              <p class="form-tip">
                与百炼「录音文件识别」里的 <code>model</code> 一致(<strong>Paraformer 系列</strong>);留空则默认 <code>paraformer-v2</code>。
                <strong>禁止</strong>填 <code>qwen*</code>、实时/口译类模型名(如 <code>qwen3-livetranslate-flash-realtime-2025-09-22</code>),那些属于另一条产品线,异步文件识别用不了。
              </p>
              <el-form-item label="语音识别模型" prop="aiSpeechModel">
                <el-input
                  v-model="baseForm.aiSpeechModel"
                  clearable
                  placeholder="paraformer-v2 或 paraformer-8k-v2;勿填 qwen / livetranslate / realtime"
                />
              </el-form-item>
              <el-divider content-position="left">对话与文本总结</el-divider>
              <p class="form-tip">OpenAI 兼容模式:用于文案总结等,需与下方模型名搭配(如兼容模式接入千问)。</p>
              <el-form-item label="对话接口地址" prop="aiChatApiUrl">
                <el-input
                  v-model="baseForm.aiChatApiUrl"
                  clearable
                  placeholder="示例:https://dashscope.aliyuncs.com/compatible-mode/v1"
                />
              </el-form-item>
              <el-form-item label="模型名称" prop="aiChatModel">
                <el-input
                  v-model="baseForm.aiChatModel"
                  clearable
                  placeholder="如 qwen-plus、qwen-turbo"
                />
              </el-form-item>
              <el-form-item label="文本 API Key" prop="aiChatApiKey">
                <el-input
                  v-model="baseForm.aiChatApiKey"
                  show-password
                  clearable
                  autocomplete="new-password"
                  placeholder="可与语音使用同一密钥或单独的子 Key"
                />
              </el-form-item>
              <el-divider content-position="left">备注归纳提示词</el-divider>
              <p class="form-tip">发给千问的 <strong>system</strong> 角色,用来约束「删掉废话、保留关键」。留空则用系统内置默认(美业健康师备注风格)。</p>
              <el-form-item label="归纳提示词" prop="aiSummarizeSystemPrompt">
                <el-input
                  v-model="baseForm.aiSummarizeSystemPrompt"
                  type="textarea"
                  :autosize="{ minRows: 5, maxRows: 18 }"
                  placeholder='例如:你是一名资深美业咨询师,请将下方口语转写整理为一句专业、可追溯的工单备注……'
                />
              </el-form-item>
              <el-form-item>
                <el-button type="primary" size="small" :loading="btnLoading" class="saveBtn"
                  @click="submitForm()">保 存</el-button>
              </el-form-item>
            </el-col>
          </el-row>
        </el-tab-pane>
      </el-tabs>
    </el-form>
  </div>
</template>

<script>
import {
  getSystemConfig,
  updateSystemConfig
} from '@/api/system/sysConfig'

export default {
  name: 'system-sysConfig',
  data() {
    return {
      defaultParaformerSubmitUrl: 'https://dashscope.aliyuncs.com/api/v1/services/audio/asr/transcription',
      activeName: 'first',
      listLoading: false,
      btnLoading: false,
      baseForm: {
        sysName: '',
        sysDescription: '',
        sysVersion: '',
        copyright: '',
        companyName: '',
        companyCode: '',
        companyAddress: '',
        companyContacts: '',
        companyTelePhone: '',
        companyEmail: '',
        singleLogin: '1',
        tokenTimeout: '1',
        lastLoginTimeSwitch: 1,
        whitelistSwitch: 1,
        whiteListIp: '',
        emailPop3Host: '',
        emailPop3Port: '110',
        emailSmtpHost: '',
        emailSmtpPort: '25',
        emailSenderName: '',
        emailAccount: '',
        emailPassword: '',
        emailSsl: 0,
        smsCompany: '1',
        smsKeyId: '',
        smsKeySecret: '',
        smsSignName: '',
        smsTemplateId: '',
        smsAppId: '',
        qyhCorpId: '',
        qyhAgentId: '',
        qyhAgentSecret: '',
        qyhCorpSecret: '',
        qyhIsSynOrg: 0,
        qyhIsSynUser: 0,
        dingSynAppKey: '',
        dingSynAppSecret: '',
        dingAgentId: '',
        dingSynIsSynOrg: 0,
        dingSynIsSynUser: 0,
        aiSpeechApiUrl: '',
        aiSpeechApiKey: '',
        aiSpeechModel: '',
        aiChatApiUrl: '',
        aiChatModel: 'qwen-plus',
        aiChatApiKey: '',
        aiSummarizeSystemPrompt: ''
      }
    }
  },
  created() {
    this.initData()
  },
  methods: {
    initData() {
      this.listLoading = true
      this.$nextTick(() => {
        getSystemConfig().then(res => {
          this.baseForm = Object.assign({}, this.baseForm, res.data || {})
          if (!this.baseForm.aiChatModel) {
            this.baseForm.aiChatModel = 'qwen-plus'
          }
          this.listLoading = false
        }).catch(() => {
          this.listLoading = false
        })
      })
    },
    submitForm() {
      this.btnLoading = true
      updateSystemConfig(this.baseForm).then(res => {
        this.$message({
          message: res.msg,
          type: 'success',
          duration: 1500,
          onClose: () => {
            this.btnLoading = false
            this.initData()
          }
        })
      }).catch(() => {
        this.btnLoading = false
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.systemConfig {
  padding: 0;
  >>> .el-card__header {
    padding: 6px 20px;
  }
  >>> .el-tabs--border-card {
    box-shadow: none;
    height: calc(100vh - 120px);
  }
  >>> .el-tabs--border-card > .el-tabs__content {
    padding: 30px 36px 10px 36px;
  }
  .saveBtn {
    width: 100px;
  }
  .form-tip {
    color: #909399;
    font-size: 13px;
    line-height: 1.6;
    margin: 0 0 12px 0;
    padding-left: 0;
  }
}
</style>