|
|
@@ -48,17 +48,142 @@
|
|
|
<el-input v-model="form.modelName" placeholder="请输入DeepSeekChat模型名称"></el-input>
|
|
|
</el-form-item>
|
|
|
</el-card>
|
|
|
+
|
|
|
+ <el-card shadow="never" class="section-card">
|
|
|
+ <div slot="header"><span>EasyCall意向评级配置</span></div>
|
|
|
+ <el-form-item label="是否启用系统意向度评级" prop="enabled">
|
|
|
+ <el-switch v-model="intentForm.enabled"></el-switch>
|
|
|
+ <span class="tip-text">启用后由本系统配置的模型进行意向评级;失败时沿用回调现有重试与未知意向度兜底</span>
|
|
|
+ </el-form-item>
|
|
|
+ <template v-if="intentForm.enabled">
|
|
|
+ <el-form-item label="当前启用模型" prop="activeCode">
|
|
|
+ <el-select
|
|
|
+ v-model="intentForm.activeCode"
|
|
|
+ placeholder="请选择启用的评级模型"
|
|
|
+ clearable
|
|
|
+ style="width: 360px"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in intentForm.models"
|
|
|
+ :key="item.code"
|
|
|
+ :label="item.name ? item.name + ' (' + item.code + ')' : item.code"
|
|
|
+ :value="item.code"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ <span class="tip-text">同时只能启用一个评级模型</span>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ <el-form-item label="评级模型列表" class="model-list-item">
|
|
|
+ <el-alert
|
|
|
+ type="info"
|
|
|
+ :closable="false"
|
|
|
+ show-icon
|
|
|
+ class="intent-save-alert"
|
|
|
+ title="新增/编辑/删除模型后,需点击页面底部「保存配置」才会写入数据库并对外呼回调生效;弹窗「确定」仅更新下方列表。"
|
|
|
+ />
|
|
|
+ <div class="model-list-toolbar">
|
|
|
+ <el-button type="primary" size="mini" icon="el-icon-plus" @click="openModelDialog()">新增模型</el-button>
|
|
|
+ </div>
|
|
|
+ <el-table
|
|
|
+ :data="intentForm.models"
|
|
|
+ border
|
|
|
+ size="small"
|
|
|
+ class="intent-model-table"
|
|
|
+ empty-text="暂无评级模型,请点击上方新增"
|
|
|
+ >
|
|
|
+ <el-table-column label="启用" width="88" align="center" class-name="enable-col">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-radio
|
|
|
+ v-model="intentForm.activeCode"
|
|
|
+ :label="scope.row.code"
|
|
|
+ class="enable-radio-only"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="编码" prop="code" min-width="140" align="center" show-overflow-tooltip />
|
|
|
+ <el-table-column label="名称" prop="name" min-width="108" align="center" show-overflow-tooltip />
|
|
|
+ <el-table-column label="Provider类型" min-width="128" align="center" show-overflow-tooltip>
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{ formatProviderType(scope.row.providerType) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="服务地址" prop="serverUrl" min-width="200" align="center" show-overflow-tooltip />
|
|
|
+ <el-table-column label="模型名称" prop="modelName" min-width="140" align="center" show-overflow-tooltip />
|
|
|
+ <el-table-column label="超时(秒)" prop="timeoutSec" width="96" align="center" />
|
|
|
+ <el-table-column label="操作" width="112" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button type="text" size="mini" @click="openModelDialog(scope.row, scope.$index)">编辑</el-button>
|
|
|
+ <el-button type="text" size="mini" class="danger-text" @click="removeModel(scope.$index)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
</el-form>
|
|
|
- <div style="text-align: center; margin-top: 20px; padding-bottom: 20px;">
|
|
|
+ <div class="page-save-bar">
|
|
|
+ <p class="save-tip-text">修改本页任意配置(含评级模型、开关等)后,请点击「保存配置」才会生效。</p>
|
|
|
<el-button type="primary" size="medium" @click="submitForm" :loading="submitLoading">保存配置</el-button>
|
|
|
</div>
|
|
|
</el-card>
|
|
|
+
|
|
|
+ <el-dialog :title="modelDialogTitle" :visible.sync="modelDialogVisible" width="640px" append-to-body @closed="resetModelForm">
|
|
|
+ <el-form ref="modelFormRef" :model="modelForm" :rules="modelRules" label-width="120px">
|
|
|
+ <el-form-item label="编码" prop="code">
|
|
|
+ <el-input v-model="modelForm.code" placeholder="唯一标识,如 DoubaoChat" :disabled="modelEditIndex >= 0" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="名称" prop="name">
|
|
|
+ <el-input v-model="modelForm.name" placeholder="展示名称,如 豆包意向评级" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="Provider类型" prop="providerType">
|
|
|
+ <el-select
|
|
|
+ v-model="modelForm.providerType"
|
|
|
+ placeholder="请选择"
|
|
|
+ style="width: 100%"
|
|
|
+ @change="onModelProviderTypeChange"
|
|
|
+ >
|
|
|
+ <el-option label="豆包 Responses API" value="doubao_responses" />
|
|
|
+ <el-option label="DeepSeek-V4 Responses API" value="deepseek_v4_responses" />
|
|
|
+ <!-- <el-option label="OpenAI 兼容 Chat" value="openai_chat" /> -->
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="服务地址" prop="serverUrl">
|
|
|
+ <el-input
|
|
|
+ v-model="modelForm.serverUrl"
|
|
|
+ :placeholder="isVolcesResponsesProvider(modelForm.providerType)
|
|
|
+ ? DEFAULT_VOLCES_RESPONSES_URL
|
|
|
+ : 'API 地址'"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="API Key" prop="apiKey">
|
|
|
+ <el-input v-model="modelForm.apiKey" placeholder="API Key" show-password />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="模型名称" prop="modelName">
|
|
|
+ <el-input v-model="modelForm.modelName" placeholder="模型名称或 Endpoint ID" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="超时(秒)" prop="timeoutSec">
|
|
|
+ <el-input-number v-model="modelForm.timeoutSec" :min="10" :max="600" :step="10" :precision="0" style="width: 100%" />
|
|
|
+ <span class="tip-text">HTTP 读超时;带 reasoning 的模型(豆包/DeepSeek-V4 等)建议 300 秒(5 分钟)以上,最大 600 秒</span>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <p class="dialog-save-tip">「确定」仅将模型写入下方列表;请点击页面底部「保存配置」后才会写入数据库并生效。</p>
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="modelDialogVisible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitModelForm">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { getConfigByKey, updateConfigByKey } from '@/api/system/config'
|
|
|
|
|
|
+/** 豆包 / DeepSeek-V4 等火山方舟 Responses API 默认地址 */
|
|
|
+const DEFAULT_VOLCES_RESPONSES_URL = 'https://ark.cn-beijing.volces.com/api/v3/responses'
|
|
|
+
|
|
|
+function isVolcesResponsesProvider(type) {
|
|
|
+ return type === 'doubao_responses' || type === 'deepseek_v4_responses'
|
|
|
+}
|
|
|
+
|
|
|
function defaultCidForm() {
|
|
|
return {
|
|
|
enablePhoneConfig: false,
|
|
|
@@ -82,15 +207,116 @@ function mergeCidForm(parsed) {
|
|
|
return { ...defaults, ...parsed }
|
|
|
}
|
|
|
|
|
|
+function defaultIntentForm() {
|
|
|
+ return {
|
|
|
+ enabled: false,
|
|
|
+ activeCode: '',
|
|
|
+ models: []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function toTimeoutSec(value) {
|
|
|
+ const sec = Number(value)
|
|
|
+ if (!Number.isFinite(sec) || sec <= 0) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ return Math.round(sec)
|
|
|
+}
|
|
|
+
|
|
|
+/** 从接口/历史配置解析为秒:优先 timeoutSec,否则兼容 timeoutMs(毫秒) */
|
|
|
+function resolveModelTimeoutSec(model) {
|
|
|
+ if (!model) {
|
|
|
+ return 300
|
|
|
+ }
|
|
|
+ const explicitSec = toTimeoutSec(model.timeoutSec)
|
|
|
+ if (explicitSec != null) {
|
|
|
+ return explicitSec
|
|
|
+ }
|
|
|
+ const ms = Number(model.timeoutMs)
|
|
|
+ if (!Number.isFinite(ms) || ms <= 0) {
|
|
|
+ return 300
|
|
|
+ }
|
|
|
+ // 历史毫秒配置
|
|
|
+ if (ms >= 1000) {
|
|
|
+ return Math.round(ms / 1000)
|
|
|
+ }
|
|
|
+ // 异常小值按秒理解
|
|
|
+ return Math.round(ms)
|
|
|
+}
|
|
|
+
|
|
|
+function normalizeModelForSave(model, options) {
|
|
|
+ if (!model || typeof model !== 'object') {
|
|
|
+ return defaultModelForm()
|
|
|
+ }
|
|
|
+ const preferForm = options && options.preferFormSec
|
|
|
+ let timeoutSec = preferForm ? toTimeoutSec(model.timeoutSec) : null
|
|
|
+ if (timeoutSec == null) {
|
|
|
+ timeoutSec = resolveModelTimeoutSec(model)
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ code: (model.code || '').trim(),
|
|
|
+ name: model.name || '',
|
|
|
+ providerType: model.providerType || 'doubao_responses',
|
|
|
+ serverUrl: model.serverUrl || '',
|
|
|
+ apiKey: model.apiKey || '',
|
|
|
+ modelName: model.modelName || '',
|
|
|
+ timeoutSec
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function defaultModelForm() {
|
|
|
+ return {
|
|
|
+ code: '',
|
|
|
+ name: '',
|
|
|
+ providerType: 'doubao_responses',
|
|
|
+ serverUrl: DEFAULT_VOLCES_RESPONSES_URL,
|
|
|
+ apiKey: '',
|
|
|
+ modelName: '',
|
|
|
+ timeoutSec: 300
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function mergeIntentForm(parsed) {
|
|
|
+ const defaults = defaultIntentForm()
|
|
|
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
|
+ return defaults
|
|
|
+ }
|
|
|
+ const models = Array.isArray(parsed.models)
|
|
|
+ ? parsed.models.map(item => normalizeModelForSave(item))
|
|
|
+ : []
|
|
|
+ return {
|
|
|
+ enabled: !!parsed.enabled,
|
|
|
+ activeCode: parsed.activeCode || '',
|
|
|
+ models
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
export default {
|
|
|
name: 'AdminCidConfig',
|
|
|
data() {
|
|
|
return {
|
|
|
+ DEFAULT_VOLCES_RESPONSES_URL,
|
|
|
loading: false,
|
|
|
submitLoading: false,
|
|
|
configId: null,
|
|
|
configKey: 'cId.config',
|
|
|
- form: defaultCidForm()
|
|
|
+ intentConfigId: null,
|
|
|
+ intentConfigKey: 'easycall.intent.rating.config',
|
|
|
+ form: defaultCidForm(),
|
|
|
+ intentForm: defaultIntentForm(),
|
|
|
+ modelDialogVisible: false,
|
|
|
+ modelDialogTitle: '新增评级模型',
|
|
|
+ modelEditIndex: -1,
|
|
|
+ modelForm: defaultModelForm(),
|
|
|
+ modelRules: {
|
|
|
+ code: [{ required: true, message: '编码不能为空', trigger: 'blur' }],
|
|
|
+ name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
|
|
+ providerType: [{ required: true, message: '请选择 Provider 类型', trigger: 'change' }],
|
|
|
+ serverUrl: [{ required: true, message: '服务地址不能为空', trigger: 'blur' }],
|
|
|
+ apiKey: [{ required: true, message: 'API Key 不能为空', trigger: 'blur' }],
|
|
|
+ modelName: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
|
|
|
+ timeoutSec: [{ required: true, message: '超时时间不能为空', trigger: 'change' }]
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
@@ -99,35 +325,189 @@ export default {
|
|
|
methods: {
|
|
|
loadConfig() {
|
|
|
this.loading = true
|
|
|
- getConfigByKey(this.configKey).then(response => {
|
|
|
- const data = response.data
|
|
|
- if (data) {
|
|
|
- this.configId = data.configId != null ? data.configId : null
|
|
|
- const configValue = data.configValue
|
|
|
- if (configValue !== null && configValue !== undefined && configValue !== '' && configValue !== 'null') {
|
|
|
- try {
|
|
|
- const parsed = JSON.parse(configValue)
|
|
|
- const {
|
|
|
- enableGateWayLimit,
|
|
|
- showGatewayIds,
|
|
|
- ...rest
|
|
|
- } = (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) ? parsed : {}
|
|
|
- this.form = mergeCidForm(rest)
|
|
|
- } catch (e) {
|
|
|
- this.form = defaultCidForm()
|
|
|
- }
|
|
|
- } else {
|
|
|
+ Promise.all([
|
|
|
+ getConfigByKey(this.configKey),
|
|
|
+ getConfigByKey(this.intentConfigKey)
|
|
|
+ ]).then(([cidRes, intentRes]) => {
|
|
|
+ this.applyCidConfig(cidRes)
|
|
|
+ this.applyIntentConfig(intentRes)
|
|
|
+ }).finally(() => {
|
|
|
+ this.loading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ applyCidConfig(response) {
|
|
|
+ const data = response.data
|
|
|
+ if (data) {
|
|
|
+ this.configId = data.configId != null ? data.configId : null
|
|
|
+ const configValue = data.configValue
|
|
|
+ if (configValue !== null && configValue !== undefined && configValue !== '' && configValue !== 'null') {
|
|
|
+ try {
|
|
|
+ const parsed = JSON.parse(configValue)
|
|
|
+ const {
|
|
|
+ enableGateWayLimit,
|
|
|
+ showGatewayIds,
|
|
|
+ ...rest
|
|
|
+ } = (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) ? parsed : {}
|
|
|
+ this.form = mergeCidForm(rest)
|
|
|
+ } catch (e) {
|
|
|
this.form = defaultCidForm()
|
|
|
}
|
|
|
} else {
|
|
|
- this.configId = null
|
|
|
this.form = defaultCidForm()
|
|
|
}
|
|
|
- }).finally(() => {
|
|
|
- this.loading = false
|
|
|
+ } else {
|
|
|
+ this.configId = null
|
|
|
+ this.form = defaultCidForm()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ applyIntentConfig(response) {
|
|
|
+ const data = response.data
|
|
|
+ if (data) {
|
|
|
+ this.intentConfigId = data.configId != null ? data.configId : null
|
|
|
+ const configValue = data.configValue
|
|
|
+ if (configValue !== null && configValue !== undefined && configValue !== '' && configValue !== 'null') {
|
|
|
+ try {
|
|
|
+ const parsed = JSON.parse(configValue)
|
|
|
+ this.intentForm = mergeIntentForm(parsed)
|
|
|
+ } catch (e) {
|
|
|
+ this.intentForm = defaultIntentForm()
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.intentForm = defaultIntentForm()
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.intentConfigId = null
|
|
|
+ this.intentForm = defaultIntentForm()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ formatProviderType(type) {
|
|
|
+ const map = {
|
|
|
+ doubao_responses: '豆包 Responses',
|
|
|
+ deepseek_v4_responses: 'DeepSeek-V4',
|
|
|
+ openai_chat: 'OpenAI Chat'
|
|
|
+ }
|
|
|
+ return map[type] || type || '-'
|
|
|
+ },
|
|
|
+ isVolcesResponsesProvider(type) {
|
|
|
+ return isVolcesResponsesProvider(type)
|
|
|
+ },
|
|
|
+ onModelProviderTypeChange(type) {
|
|
|
+ if (isVolcesResponsesProvider(type) && !(this.modelForm.serverUrl || '').trim()) {
|
|
|
+ this.modelForm.serverUrl = DEFAULT_VOLCES_RESPONSES_URL
|
|
|
+ }
|
|
|
+ },
|
|
|
+ displayTimeoutSec(model) {
|
|
|
+ return resolveModelTimeoutSec(model)
|
|
|
+ },
|
|
|
+ /** 保存总配置前,将弹窗内未点「确定」的编辑同步到 models */
|
|
|
+ flushPendingModelDialog() {
|
|
|
+ if (!this.modelDialogVisible || !this.modelForm) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ const code = (this.modelForm.code || '').trim()
|
|
|
+ if (!code) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ const timeoutSec = toTimeoutSec(this.modelForm.timeoutSec)
|
|
|
+ if (timeoutSec == null) {
|
|
|
+ this.msgError('请先完善弹窗中的超时(秒)后再保存')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ const payload = normalizeModelForSave({ ...this.modelForm, code, timeoutSec }, { preferFormSec: true })
|
|
|
+ if (this.modelEditIndex >= 0) {
|
|
|
+ const duplicateIndex = this.intentForm.models.findIndex(item => item.code === code)
|
|
|
+ if (duplicateIndex >= 0 && duplicateIndex !== this.modelEditIndex) {
|
|
|
+ this.msgError('模型编码已存在')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ const oldCode = this.intentForm.models[this.modelEditIndex].code
|
|
|
+ this.$set(this.intentForm.models, this.modelEditIndex, payload)
|
|
|
+ if (this.intentForm.activeCode === oldCode) {
|
|
|
+ this.intentForm.activeCode = code
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ const duplicateIndex = this.intentForm.models.findIndex(item => item.code === code)
|
|
|
+ if (duplicateIndex >= 0) {
|
|
|
+ this.msgError('模型编码已存在,请先关闭弹窗或修改编码')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ this.intentForm.models.push(payload)
|
|
|
+ if (!this.intentForm.activeCode) {
|
|
|
+ this.intentForm.activeCode = code
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.modelDialogVisible = false
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ openModelDialog(row, index) {
|
|
|
+ if (row && index >= 0) {
|
|
|
+ this.modelDialogTitle = '编辑评级模型'
|
|
|
+ this.modelEditIndex = index
|
|
|
+ this.modelForm = normalizeModelForSave(row)
|
|
|
+ } else {
|
|
|
+ this.modelDialogTitle = '新增评级模型'
|
|
|
+ this.modelEditIndex = -1
|
|
|
+ this.modelForm = defaultModelForm()
|
|
|
+ }
|
|
|
+ this.modelDialogVisible = true
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.modelFormRef) {
|
|
|
+ this.$refs.modelFormRef.clearValidate()
|
|
|
+ }
|
|
|
})
|
|
|
},
|
|
|
- submitForm() {
|
|
|
+ resetModelForm() {
|
|
|
+ this.modelEditIndex = -1
|
|
|
+ this.modelForm = defaultModelForm()
|
|
|
+ },
|
|
|
+ submitModelForm() {
|
|
|
+ this.$refs.modelFormRef.validate(valid => {
|
|
|
+ if (!valid) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const code = (this.modelForm.code || '').trim()
|
|
|
+ const duplicateIndex = this.intentForm.models.findIndex(item => item.code === code)
|
|
|
+ if (this.modelEditIndex < 0 && duplicateIndex >= 0) {
|
|
|
+ this.msgError('模型编码已存在')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.modelEditIndex >= 0 && duplicateIndex >= 0 && duplicateIndex !== this.modelEditIndex) {
|
|
|
+ this.msgError('模型编码已存在')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const payload = normalizeModelForSave({ ...this.modelForm, code }, { preferFormSec: true })
|
|
|
+ if (this.modelEditIndex >= 0) {
|
|
|
+ const oldCode = this.intentForm.models[this.modelEditIndex].code
|
|
|
+ this.$set(this.intentForm.models, this.modelEditIndex, payload)
|
|
|
+ if (this.intentForm.activeCode === oldCode) {
|
|
|
+ this.intentForm.activeCode = code
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.intentForm.models.push(payload)
|
|
|
+ if (!this.intentForm.activeCode) {
|
|
|
+ this.intentForm.activeCode = code
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.modelDialogVisible = false
|
|
|
+ this.msgInfo('模型已更新到列表,请点击页面底部「保存配置」后才会生效')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ removeModel(index) {
|
|
|
+ const row = this.intentForm.models[index]
|
|
|
+ if (!row) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.$confirm('确认删除评级模型「' + (row.name || row.code) + '」吗?', '提示', {
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ if (this.intentForm.activeCode === row.code) {
|
|
|
+ this.intentForm.activeCode = ''
|
|
|
+ }
|
|
|
+ this.intentForm.models.splice(index, 1)
|
|
|
+ this.msgInfo('模型已从列表移除,请点击页面底部「保存配置」后才会生效')
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
+ validateCidForm() {
|
|
|
if (this.form.enablePhoneConfig) {
|
|
|
if (!this.form.generateCount || this.form.generateCount < 1) {
|
|
|
this.msgError('生成条数不能为空且不能小于1')
|
|
|
@@ -165,17 +545,63 @@ export default {
|
|
|
return false
|
|
|
}
|
|
|
}
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ validateIntentForm() {
|
|
|
+ if (!this.intentForm.enabled) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ if (!this.intentForm.models.length) {
|
|
|
+ this.msgError('请至少添加一个评级模型')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!this.intentForm.activeCode) {
|
|
|
+ this.msgError('请选择当前启用的评级模型')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ const activeModel = this.intentForm.models.find(item => item.code === this.intentForm.activeCode)
|
|
|
+ if (!activeModel) {
|
|
|
+ this.msgError('当前启用的模型不存在,请重新选择')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ submitForm() {
|
|
|
+ if (!this.validateCidForm() || !this.validateIntentForm()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.flushPendingModelDialog()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
this.submitLoading = true
|
|
|
- const param = {
|
|
|
+ const cidParam = {
|
|
|
configId: (this.configId != null && this.configId !== '') ? Number(this.configId) : null,
|
|
|
configName: 'CID配置',
|
|
|
configKey: this.configKey,
|
|
|
configValue: JSON.stringify(this.form)
|
|
|
}
|
|
|
- updateConfigByKey(param).then(response => {
|
|
|
- if (response.code === 200) {
|
|
|
- this.msgSuccess(this.configId ? '修改成功' : '保存成功')
|
|
|
+ const intentPayload = {
|
|
|
+ enabled: !!this.intentForm.enabled,
|
|
|
+ activeCode: this.intentForm.activeCode || '',
|
|
|
+ models: this.intentForm.models.map(item => normalizeModelForSave(item))
|
|
|
+ }
|
|
|
+ const intentParam = {
|
|
|
+ configId: (this.intentConfigId != null && this.intentConfigId !== '') ? Number(this.intentConfigId) : null,
|
|
|
+ configName: 'EasyCall意向评级配置',
|
|
|
+ configKey: this.intentConfigKey,
|
|
|
+ configValue: JSON.stringify(intentPayload)
|
|
|
+ }
|
|
|
+ Promise.all([
|
|
|
+ updateConfigByKey(cidParam),
|
|
|
+ updateConfigByKey(intentParam)
|
|
|
+ ]).then(([cidResponse, intentResponse]) => {
|
|
|
+ if (cidResponse.code === 200 && intentResponse.code === 200) {
|
|
|
+ this.msgSuccess('保存成功')
|
|
|
this.loadConfig()
|
|
|
+ } else if (cidResponse.code !== 200) {
|
|
|
+ this.msgError(cidResponse.msg || 'CID配置保存失败')
|
|
|
+ } else {
|
|
|
+ this.msgError(intentResponse.msg || '意向评级配置保存失败')
|
|
|
}
|
|
|
}).finally(() => {
|
|
|
this.submitLoading = false
|
|
|
@@ -194,4 +620,61 @@ export default {
|
|
|
font-size: 12px;
|
|
|
margin-left: 8px;
|
|
|
}
|
|
|
+.danger-text {
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+.model-list-item >>> .el-form-item__label {
|
|
|
+ float: none;
|
|
|
+ display: block;
|
|
|
+ width: 100% !important;
|
|
|
+ text-align: left;
|
|
|
+ padding-bottom: 8px;
|
|
|
+}
|
|
|
+.model-list-item >>> .el-form-item__content {
|
|
|
+ margin-left: 0 !important;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+.model-list-toolbar {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ margin-top: 12px;
|
|
|
+}
|
|
|
+.intent-save-alert {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+.page-save-bar {
|
|
|
+ text-align: center;
|
|
|
+ margin-top: 20px;
|
|
|
+ padding-bottom: 20px;
|
|
|
+}
|
|
|
+.save-tip-text {
|
|
|
+ color: #e6a23c;
|
|
|
+ font-size: 13px;
|
|
|
+ margin: 0 0 12px;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+.dialog-save-tip {
|
|
|
+ color: #909399;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 1.6;
|
|
|
+ margin: 0 0 4px;
|
|
|
+ padding: 0 4px;
|
|
|
+}
|
|
|
+.intent-model-table {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+.intent-model-table >>> .cell {
|
|
|
+ padding-left: 8px;
|
|
|
+ padding-right: 8px;
|
|
|
+}
|
|
|
+.intent-model-table >>> .enable-radio-only .el-radio__label {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+.intent-model-table >>> .enable-radio-only .el-radio__input {
|
|
|
+ margin-right: 0;
|
|
|
+}
|
|
|
+.intent-model-table >>> td.enable-col .cell {
|
|
|
+ overflow: visible;
|
|
|
+ padding-left: 4px;
|
|
|
+ padding-right: 4px;
|
|
|
+}
|
|
|
</style>
|