557 lines
15 KiB
Vue
557 lines
15 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="knowledge-basic-container">
|
|||
|
|
<!-- 查看模式 -->
|
|||
|
|
<div v-if="type === 'view'" class="view-mode">
|
|||
|
|
<div class="info-section">
|
|||
|
|
<div class="avatar-section">
|
|||
|
|
<img v-if="knowledge?.avatar" :src="FILE_DOWNLOAD_URL + knowledge.avatar" alt="知识库头像" />
|
|||
|
|
<div v-else class="default-avatar">📚</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="info-details">
|
|||
|
|
<h2 class="knowledge-name">{{ knowledge?.title || '未命名' }}</h2>
|
|||
|
|
<p class="knowledge-description">{{ knowledge?.description || '暂无描述' }}</p>
|
|||
|
|
<div class="meta-info">
|
|||
|
|
<div class="meta-item">
|
|||
|
|
<span class="label">状态:</span>
|
|||
|
|
<el-tag :type="knowledge?.status === 1 ? 'success' : 'info'" size="small">
|
|||
|
|
{{ knowledge?.status === 1 ? '已启用' : '已禁用' }}
|
|||
|
|
</el-tag>
|
|||
|
|
</div>
|
|||
|
|
<div class="meta-item" v-if="knowledge?.difyDatasetId">
|
|||
|
|
<span class="label">Dify数据集ID:</span>
|
|||
|
|
<span class="value">{{ knowledge.difyDatasetId }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="meta-item">
|
|||
|
|
<span class="label">索引方式:</span>
|
|||
|
|
<span class="value">{{ getIndexingText(knowledge?.difyIndexingTechnique) }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="meta-item" v-if="knowledge?.difyIndexingTechnique == 'high_quality'">
|
|||
|
|
<span class="label">Embedding模型:</span>
|
|||
|
|
<span class="value">{{ knowledge?.embeddingModel || '-' }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="meta-item">
|
|||
|
|
<span class="label">文档数量:</span>
|
|||
|
|
<span class="value">{{ knowledge?.documentCount || 0 }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="meta-item">
|
|||
|
|
<span class="label">创建时间:</span>
|
|||
|
|
<span class="value">{{ formatDate(knowledge?.createTime) }}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 新增/编辑模式 -->
|
|||
|
|
<div v-else class="edit-mode">
|
|||
|
|
<el-form
|
|||
|
|
ref="formRef"
|
|||
|
|
:model="formData"
|
|||
|
|
:rules="rules"
|
|||
|
|
label-position="top"
|
|||
|
|
class="knowledge-form"
|
|||
|
|
>
|
|||
|
|
<el-form-item label="知识库标题" prop="title" required>
|
|||
|
|
<el-input
|
|||
|
|
v-model="formData.title"
|
|||
|
|
placeholder="请输入知识库标题"
|
|||
|
|
maxlength="100"
|
|||
|
|
show-word-limit
|
|||
|
|
:disabled="props.type === 'view'"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<el-form-item label="知识库头像" prop="avatar">
|
|||
|
|
<FileUpload
|
|||
|
|
:cover-url="formData.avatar"
|
|||
|
|
@update:cover-url="handleAvatarUpdate"
|
|||
|
|
:as-dialog="false"
|
|||
|
|
list-type="cover"
|
|||
|
|
accept="image/*"
|
|||
|
|
:max-size="2"
|
|||
|
|
module="ai-knowledge"
|
|||
|
|
tip="点击上传知识库头像"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<el-form-item label="知识库描述" prop="description">
|
|||
|
|
<el-input
|
|||
|
|
v-model="formData.description"
|
|||
|
|
type="textarea"
|
|||
|
|
:rows="4"
|
|||
|
|
placeholder="请输入知识库描述,介绍知识库的内容、用途等..."
|
|||
|
|
maxlength="500"
|
|||
|
|
show-word-limit
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<el-form-item label="索引方式" prop="difyIndexingTechnique" required>
|
|||
|
|
<el-radio-group v-model="formData.difyIndexingTechnique">
|
|||
|
|
<el-radio value="high_quality">
|
|||
|
|
<span class="radio-label">高质量</span>
|
|||
|
|
<span class="radio-desc">更精确的检索结果,消耗更多tokens</span>
|
|||
|
|
</el-radio>
|
|||
|
|
<el-radio
|
|||
|
|
value="economy"
|
|||
|
|
:disabled="type === 'edit' && knowledge?.difyIndexingTechnique === 'high_quality'"
|
|||
|
|
>
|
|||
|
|
<span class="radio-label">经济</span>
|
|||
|
|
<span class="radio-desc">快速检索,消耗较少tokens</span>
|
|||
|
|
</el-radio>
|
|||
|
|
</el-radio-group>
|
|||
|
|
<div v-if="type === 'edit' && knowledge?.difyIndexingTechnique === 'high_quality'" class="form-tip">
|
|||
|
|
高质量模式不能降级为经济模式
|
|||
|
|
</div>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<el-form-item v-if="formData.difyIndexingTechnique == 'high_quality'" label="Embedding模型" prop="embeddingModel">
|
|||
|
|
<el-select
|
|||
|
|
v-model="formData.embeddingModel"
|
|||
|
|
placeholder="请选择Embedding模型(可选)"
|
|||
|
|
clearable
|
|||
|
|
filterable
|
|||
|
|
:loading="modelsLoading"
|
|||
|
|
@change="handleModelChange"
|
|||
|
|
>
|
|||
|
|
<el-option-group
|
|||
|
|
v-for="provider in embeddingModels"
|
|||
|
|
:key="provider.provider"
|
|||
|
|
:label="provider.label || provider.provider"
|
|||
|
|
>
|
|||
|
|
<el-option
|
|||
|
|
v-for="model in provider.models"
|
|||
|
|
:key="model.model"
|
|||
|
|
:label="getModelLabel(model)"
|
|||
|
|
:value="model.model"
|
|||
|
|
:data-provider="model.provider"
|
|||
|
|
>
|
|||
|
|
<span>{{ getModelLabel(model) }}</span>
|
|||
|
|
<span v-if="model.contextSize" style="float: right; color: var(--el-text-color-secondary); font-size: 13px">
|
|||
|
|
上下文: {{ model.contextSize }}
|
|||
|
|
</span>
|
|||
|
|
</el-option>
|
|||
|
|
</el-option-group>
|
|||
|
|
</el-select>
|
|||
|
|
<div v-if="type === 'edit'" class="form-tip form-tip-success">
|
|||
|
|
可以切换Embedding模型以优化检索效果
|
|||
|
|
</div>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<el-form-item label="Dify数据集ID" prop="difyDatasetId">
|
|||
|
|
<el-input
|
|||
|
|
v-model="formData.difyDatasetId"
|
|||
|
|
placeholder="可选,如需关联现有Dify数据集请填写"
|
|||
|
|
:disabled="type === 'edit'"
|
|||
|
|
/>
|
|||
|
|
<div v-if="type === 'edit'" class="form-tip">
|
|||
|
|
Dify数据集ID创建后不可修改
|
|||
|
|
</div>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<el-form-item label="状态" prop="status">
|
|||
|
|
<el-switch
|
|||
|
|
v-model="formData.status"
|
|||
|
|
:active-value="1"
|
|||
|
|
:inactive-value="0"
|
|||
|
|
active-text="启用"
|
|||
|
|
inactive-text="禁用"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<div class="form-actions">
|
|||
|
|
<el-button type="primary" @click="handleSubmit" :loading="submitting">
|
|||
|
|
{{ type === 'add' ? '创建知识库' : '保存修改' }}
|
|||
|
|
</el-button>
|
|||
|
|
<el-button @click="handleCancel">
|
|||
|
|
取消
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</el-form>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup lang="ts">
|
|||
|
|
import { ref, reactive, watch } from 'vue';
|
|||
|
|
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
|
|||
|
|
import { FileUpload } from '@/components/file';
|
|||
|
|
import type { AiKnowledge } from '@/types/ai';
|
|||
|
|
import { knowledgeApi } from '@/apis/ai';
|
|||
|
|
import { FILE_DOWNLOAD_URL } from '@/config';
|
|||
|
|
|
|||
|
|
defineOptions({
|
|||
|
|
name: 'KnowledgeBasic'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
interface KnowledgeBasicProps {
|
|||
|
|
type: 'view' | 'add' | 'edit';
|
|||
|
|
knowledge?: AiKnowledge | null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const props = defineProps<KnowledgeBasicProps>();
|
|||
|
|
const emit = defineEmits<{
|
|||
|
|
success: [knowledge: AiKnowledge];
|
|||
|
|
cancel: [];
|
|||
|
|
}>();
|
|||
|
|
|
|||
|
|
// 表单引用
|
|||
|
|
const formRef = ref<FormInstance>();
|
|||
|
|
const submitting = ref(false);
|
|||
|
|
const modelsLoading = ref(false);
|
|||
|
|
const embeddingModels = ref<any[]>([]);
|
|||
|
|
|
|||
|
|
// 表单数据
|
|||
|
|
const formData = reactive<Partial<AiKnowledge>>({
|
|||
|
|
title: '',
|
|||
|
|
avatar: '',
|
|||
|
|
description: '',
|
|||
|
|
difyIndexingTechnique: 'high_quality',
|
|||
|
|
embeddingModel: '',
|
|||
|
|
embeddingModelProvider: '',
|
|||
|
|
difyDatasetId: '',
|
|||
|
|
status: 1
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 表单验证规则
|
|||
|
|
const rules: FormRules = {
|
|||
|
|
title: [
|
|||
|
|
{ required: true, message: '请输入知识库标题', trigger: 'blur' },
|
|||
|
|
{ min: 2, max: 100, message: '标题长度在2-100个字符之间', trigger: 'blur' }
|
|||
|
|
],
|
|||
|
|
difyIndexingTechnique: [
|
|||
|
|
{ required: true, message: '请选择索引方式', trigger: 'change' }
|
|||
|
|
]
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 监听知识库数据变化
|
|||
|
|
watch(() => props.knowledge, (newVal) => {
|
|||
|
|
if (newVal && (props.type === 'view' || props.type === 'edit')) {
|
|||
|
|
Object.assign(formData, {
|
|||
|
|
id: newVal.id,
|
|||
|
|
title: newVal.title,
|
|||
|
|
avatar: newVal.avatar,
|
|||
|
|
description: newVal.description,
|
|||
|
|
difyIndexingTechnique: newVal.difyIndexingTechnique || 'high_quality',
|
|||
|
|
embeddingModel: newVal.embeddingModel,
|
|||
|
|
embeddingModelProvider: newVal.embeddingModelProvider,
|
|||
|
|
difyDatasetId: newVal.difyDatasetId,
|
|||
|
|
status: newVal.status ?? 1
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}, { immediate: true });
|
|||
|
|
|
|||
|
|
// 处理头像更新
|
|||
|
|
function handleAvatarUpdate(val: string) {
|
|||
|
|
formData.avatar = val;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 加载嵌入模型列表
|
|||
|
|
async function loadEmbeddingModels() {
|
|||
|
|
try {
|
|||
|
|
modelsLoading.value = true;
|
|||
|
|
const result = await knowledgeApi.getAvailableEmbeddingModels();
|
|||
|
|
if (result.success && result.data) {
|
|||
|
|
// 按提供商分组
|
|||
|
|
const providers = result.data.providers || [];
|
|||
|
|
embeddingModels.value = providers.map((provider: any) => ({
|
|||
|
|
provider: provider.provider,
|
|||
|
|
label: provider.label?.zh_Hans || provider.label?.en_US || provider.provider,
|
|||
|
|
models: (provider.models || []).map((model: any) => ({
|
|||
|
|
model: model.model,
|
|||
|
|
provider: model.provider || provider.provider, // 添加 provider 到 model 对象
|
|||
|
|
label: model.label?.zh_Hans || model.label?.en_US || model.model,
|
|||
|
|
contextSize: model.model_properties?.context_size,
|
|||
|
|
status: model.status
|
|||
|
|
}))
|
|||
|
|
}));
|
|||
|
|
} else {
|
|||
|
|
ElMessage.warning('获取嵌入模型列表失败,使用默认选项');
|
|||
|
|
// 设置默认模型列表
|
|||
|
|
embeddingModels.value = [{
|
|||
|
|
provider: 'openai',
|
|||
|
|
label: 'OpenAI',
|
|||
|
|
models: [
|
|||
|
|
{ model: 'text-embedding-ada-002', label: 'text-embedding-ada-002' },
|
|||
|
|
{ model: 'text-embedding-3-small', label: 'text-embedding-3-small' },
|
|||
|
|
{ model: 'text-embedding-3-large', label: 'text-embedding-3-large' }
|
|||
|
|
]
|
|||
|
|
}];
|
|||
|
|
}
|
|||
|
|
} catch (error: any) {
|
|||
|
|
console.error('加载嵌入模型列表失败:', error);
|
|||
|
|
// 设置默认模型列表
|
|||
|
|
embeddingModels.value = [{
|
|||
|
|
provider: 'openai',
|
|||
|
|
label: 'OpenAI',
|
|||
|
|
models: [
|
|||
|
|
{ model: 'text-embedding-ada-002', label: 'text-embedding-ada-002' },
|
|||
|
|
{ model: 'text-embedding-3-small', label: 'text-embedding-3-small' },
|
|||
|
|
{ model: 'text-embedding-3-large', label: 'text-embedding-3-large' }
|
|||
|
|
]
|
|||
|
|
}];
|
|||
|
|
} finally {
|
|||
|
|
modelsLoading.value = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取模型显示标签
|
|||
|
|
function getModelLabel(model: any): string {
|
|||
|
|
return model.label || model.model;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理模型变化
|
|||
|
|
function handleModelChange(modelName: string) {
|
|||
|
|
if (!modelName) {
|
|||
|
|
formData.embeddingModelProvider = '';
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查找选中模型的提供商
|
|||
|
|
for (const providerGroup of embeddingModels.value) {
|
|||
|
|
const foundModel = providerGroup.models.find((m: any) => m.model === modelName);
|
|||
|
|
if (foundModel) {
|
|||
|
|
formData.embeddingModelProvider = foundModel.provider;
|
|||
|
|
console.log('选择模型:', modelName, '提供商:', foundModel.provider);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 组件挂载时加载模型列表
|
|||
|
|
loadEmbeddingModels();
|
|||
|
|
|
|||
|
|
// 提交表单
|
|||
|
|
async function handleSubmit() {
|
|||
|
|
if (!formRef.value) return;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const valid = await formRef.value.validate();
|
|||
|
|
if (!valid) return;
|
|||
|
|
|
|||
|
|
submitting.value = true;
|
|||
|
|
|
|||
|
|
if (props.type === 'add') {
|
|||
|
|
// 创建知识库
|
|||
|
|
const result = await knowledgeApi.createKnowledge(formData as AiKnowledge);
|
|||
|
|
if (result.success && result.data) {
|
|||
|
|
ElMessage.success('创建成功');
|
|||
|
|
emit('success', result.data);
|
|||
|
|
} else {
|
|||
|
|
ElMessage.error(result.message || '创建失败');
|
|||
|
|
}
|
|||
|
|
} else if (props.type === 'edit') {
|
|||
|
|
// 更新知识库
|
|||
|
|
const result = await knowledgeApi.updateKnowledge(formData as AiKnowledge);
|
|||
|
|
if (result.success && result.data) {
|
|||
|
|
ElMessage.success('保存成功');
|
|||
|
|
emit('success', result.data);
|
|||
|
|
} else {
|
|||
|
|
ElMessage.error(result.message || '保存失败');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (error: any) {
|
|||
|
|
console.error('提交失败:', error);
|
|||
|
|
ElMessage.error(props.type === 'add' ? '创建失败' : '保存失败');
|
|||
|
|
} finally {
|
|||
|
|
submitting.value = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 取消操作
|
|||
|
|
function handleCancel() {
|
|||
|
|
emit('cancel');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取索引方式文本
|
|||
|
|
function getIndexingText(technique: string | undefined): string {
|
|||
|
|
switch (technique) {
|
|||
|
|
case 'high_quality':
|
|||
|
|
return '高质量';
|
|||
|
|
case 'economy':
|
|||
|
|
return '经济';
|
|||
|
|
default:
|
|||
|
|
return '-';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 格式化日期
|
|||
|
|
function formatDate(date: string | Date | undefined): string {
|
|||
|
|
if (!date) return '-';
|
|||
|
|
const d = new Date(date);
|
|||
|
|
if (isNaN(d.getTime())) return '-';
|
|||
|
|
return d.toLocaleString('zh-CN', {
|
|||
|
|
year: 'numeric',
|
|||
|
|
month: '2-digit',
|
|||
|
|
day: '2-digit',
|
|||
|
|
hour: '2-digit',
|
|||
|
|
minute: '2-digit'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.knowledge-basic-container {
|
|||
|
|
padding: 24px;
|
|||
|
|
background: #FFFFFF;
|
|||
|
|
border-radius: 14px;
|
|||
|
|
min-height: 400px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查看模式样式
|
|||
|
|
.view-mode {
|
|||
|
|
.info-section {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 24px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.avatar-section {
|
|||
|
|
width: 120px;
|
|||
|
|
height: 120px;
|
|||
|
|
border-radius: 12px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
background: #F8F9FA;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|||
|
|
|
|||
|
|
img {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
object-fit: cover;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.default-avatar {
|
|||
|
|
font-size: 48px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-details {
|
|||
|
|
flex: 1;
|
|||
|
|
min-width: 0;
|
|||
|
|
|
|||
|
|
.knowledge-name {
|
|||
|
|
font-size: 24px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #101828;
|
|||
|
|
margin: 0 0 12px 0;
|
|||
|
|
letter-spacing: -0.02em;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.knowledge-description {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #667085;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
margin: 0 0 24px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.meta-info {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|||
|
|
gap: 16px;
|
|||
|
|
|
|||
|
|
.meta-item {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 8px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
|
|||
|
|
.label {
|
|||
|
|
color: #667085;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.value {
|
|||
|
|
color: #101828;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 编辑模式样式
|
|||
|
|
.edit-mode {
|
|||
|
|
.knowledge-form {
|
|||
|
|
max-width: 600px;
|
|||
|
|
|
|||
|
|
:deep(.el-form-item__label) {
|
|||
|
|
font-weight: 500;
|
|||
|
|
color: #101828;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-radio) {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
height: auto;
|
|||
|
|
|
|||
|
|
.el-radio__label {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 4px;
|
|||
|
|
white-space: normal;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.radio-label {
|
|||
|
|
font-weight: 500;
|
|||
|
|
color: #101828;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.radio-desc {
|
|||
|
|
font-size: 13px;
|
|||
|
|
color: #667085;
|
|||
|
|
line-height: 1.4;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.form-tip {
|
|||
|
|
margin-top: 8px;
|
|||
|
|
font-size: 13px;
|
|||
|
|
color: #F59E0B;
|
|||
|
|
line-height: 1.4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.form-tip-success {
|
|||
|
|
color: #67C23A;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.form-actions {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 12px;
|
|||
|
|
margin-top: 32px;
|
|||
|
|
padding-top: 24px;
|
|||
|
|
border-top: 1px solid #F3F3F5;
|
|||
|
|
|
|||
|
|
.el-button {
|
|||
|
|
border-radius: 8px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
padding: 12px 24px;
|
|||
|
|
|
|||
|
|
&.el-button--primary {
|
|||
|
|
background: #E7000B;
|
|||
|
|
border-color: #E7000B;
|
|||
|
|
|
|||
|
|
&:hover {
|
|||
|
|
background: #C90009;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-switch) {
|
|||
|
|
.el-switch__label {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #667085;
|
|||
|
|
|
|||
|
|
&.is-active {
|
|||
|
|
color: #E7000B;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|