feat: 增加知识库新类型FAQ知识库
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import {computed, onMounted, ref} from 'vue';
|
||||
import {useRoute, useRouter} from 'vue-router';
|
||||
|
||||
import { $t } from '@easyflow/locales';
|
||||
import {$t} from '@easyflow/locales';
|
||||
|
||||
import { ArrowLeft, Plus } from '@element-plus/icons-vue';
|
||||
import { ElIcon, ElImage } from 'element-plus';
|
||||
import {ArrowLeft, Plus} from '@element-plus/icons-vue';
|
||||
import {ElIcon, ElImage} from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import {api} from '#/api/request';
|
||||
import bookIcon from '#/assets/ai/knowledge/book.svg';
|
||||
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
|
||||
import PageSide from '#/components/page/PageSide.vue';
|
||||
import ChunkDocumentTable from '#/views/ai/documentCollection/ChunkDocumentTable.vue';
|
||||
import DocumentCollectionDataConfig from '#/views/ai/documentCollection/DocumentCollectionDataConfig.vue';
|
||||
import DocumentCollectionDataConfig
|
||||
from '#/views/ai/documentCollection/DocumentCollectionDataConfig.vue';
|
||||
import DocumentTable from '#/views/ai/documentCollection/DocumentTable.vue';
|
||||
import FaqTable from '#/views/ai/documentCollection/FaqTable.vue';
|
||||
import ImportKnowledgeDocFile from '#/views/ai/documentCollection/ImportKnowledgeDocFile.vue';
|
||||
import KnowledgeSearch from '#/views/ai/documentCollection/KnowledgeSearch.vue';
|
||||
import KnowledgeSearchConfig from '#/views/ai/documentCollection/KnowledgeSearchConfig.vue';
|
||||
@@ -24,6 +26,21 @@ const router = useRouter();
|
||||
const knowledgeId = ref<string>((route.query.id as string) || '');
|
||||
const activeMenu = ref<string>((route.query.activeMenu as string) || '');
|
||||
const knowledgeInfo = ref<any>({});
|
||||
const selectedCategory = ref('');
|
||||
const defaultSelectedMenu = ref('');
|
||||
|
||||
const resolveDefaultMenu = (collectionType: string, menuKey: string) => {
|
||||
const faqMenus = new Set(['faqList', 'knowledgeSearch', 'config']);
|
||||
const documentMenus = new Set(['documentList', 'knowledgeSearch', 'config']);
|
||||
const fallbackMenu = collectionType === 'FAQ' ? 'faqList' : 'documentList';
|
||||
|
||||
if (!menuKey) {
|
||||
return fallbackMenu;
|
||||
}
|
||||
const validMenuSet = collectionType === 'FAQ' ? faqMenus : documentMenus;
|
||||
return validMenuSet.has(menuKey) ? menuKey : fallbackMenu;
|
||||
};
|
||||
|
||||
const getKnowledge = () => {
|
||||
api
|
||||
.get('/api/v1/documentCollection/detail', {
|
||||
@@ -32,23 +49,36 @@ const getKnowledge = () => {
|
||||
.then((res) => {
|
||||
if (res.errorCode === 0) {
|
||||
knowledgeInfo.value = res.data;
|
||||
const initialMenu = resolveDefaultMenu(
|
||||
res.data.collectionType || 'DOCUMENT',
|
||||
activeMenu.value,
|
||||
);
|
||||
defaultSelectedMenu.value = initialMenu;
|
||||
selectedCategory.value = initialMenu;
|
||||
}
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
if (activeMenu.value) {
|
||||
defaultSelectedMenu.value = activeMenu.value;
|
||||
}
|
||||
getKnowledge();
|
||||
});
|
||||
const back = () => {
|
||||
router.push({ path: '/ai/documentCollection' });
|
||||
};
|
||||
const categoryData = [
|
||||
{ key: 'documentList', name: $t('documentCollection.documentList') },
|
||||
{ key: 'knowledgeSearch', name: $t('documentCollection.knowledgeRetrieval') },
|
||||
{ key: 'config', name: $t('documentCollection.config') },
|
||||
];
|
||||
const isFaqCollection = computed(() => knowledgeInfo.value.collectionType === 'FAQ');
|
||||
const categoryData = computed(() => {
|
||||
if (isFaqCollection.value) {
|
||||
return [
|
||||
{ key: 'faqList', name: $t('documentCollection.faq.faqList') },
|
||||
{ key: 'knowledgeSearch', name: $t('documentCollection.knowledgeRetrieval') },
|
||||
{ key: 'config', name: $t('documentCollection.config') },
|
||||
];
|
||||
}
|
||||
return [
|
||||
{ key: 'documentList', name: $t('documentCollection.documentList') },
|
||||
{ key: 'knowledgeSearch', name: $t('documentCollection.knowledgeRetrieval') },
|
||||
{ key: 'config', name: $t('documentCollection.config') },
|
||||
];
|
||||
});
|
||||
const headerButtons = [
|
||||
{
|
||||
key: 'importFile',
|
||||
@@ -59,7 +89,6 @@ const headerButtons = [
|
||||
},
|
||||
];
|
||||
const isImportFileVisible = ref(false);
|
||||
const selectedCategory = ref('documentList');
|
||||
const documentTableRef = ref();
|
||||
const handleSearch = (searchParams: string) => {
|
||||
documentTableRef.value.search(searchParams);
|
||||
@@ -91,7 +120,6 @@ const viewDoc = (docId: string) => {
|
||||
const backDoc = () => {
|
||||
isImportFileVisible.value = false;
|
||||
};
|
||||
const defaultSelectedMenu = ref('documentList');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -127,6 +155,7 @@ const defaultSelectedMenu = ref('documentList');
|
||||
<div v-if="selectedCategory === 'documentList'" class="doc-table">
|
||||
<div class="doc-header" v-if="!viewDocVisible">
|
||||
<HeaderSearch
|
||||
v-if="!isFaqCollection"
|
||||
:buttons="headerButtons"
|
||||
@search="handleSearch"
|
||||
@button-click="handleButtonClick"
|
||||
@@ -145,6 +174,9 @@ const defaultSelectedMenu = ref('documentList');
|
||||
:default-summary-prompt="knowledgeInfo.summaryPrompt"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="selectedCategory === 'faqList'" class="doc-table">
|
||||
<FaqTable :knowledge-id="knowledgeId" />
|
||||
</div>
|
||||
<!--知识检索-->
|
||||
<div
|
||||
v-if="selectedCategory === 'knowledgeSearch'"
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormInstance } from 'element-plus';
|
||||
|
||||
import type { ActionButton } from '#/components/page/CardList.vue';
|
||||
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { Delete, Edit, Notebook, Plus, Search } from '@element-plus/icons-vue';
|
||||
import type {FormInstance} from 'element-plus';
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
@@ -19,17 +10,30 @@ import {
|
||||
ElMessage,
|
||||
ElMessageBox,
|
||||
} from 'element-plus';
|
||||
import { tryit } from 'radash';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import type {ActionButton} from '#/components/page/CardList.vue';
|
||||
import CardPage from '#/components/page/CardList.vue';
|
||||
|
||||
import {computed, onMounted, ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
|
||||
import {Delete, Edit, Notebook, Plus, Search} from '@element-plus/icons-vue';
|
||||
import {tryit} from 'radash';
|
||||
|
||||
import {api} from '#/api/request';
|
||||
import defaultIcon from '#/assets/ai/knowledge/book.svg';
|
||||
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
|
||||
import CardPage from '#/components/page/CardList.vue';
|
||||
import PageData from '#/components/page/PageData.vue';
|
||||
import PageSide from '#/components/page/PageSide.vue';
|
||||
import DocumentCollectionModal from '#/views/ai/documentCollection/DocumentCollectionModal.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const collectionTypeLabelMap = {
|
||||
DOCUMENT: $t('documentCollection.collectionTypeDocument'),
|
||||
FAQ: $t('documentCollection.collectionTypeFaq'),
|
||||
};
|
||||
interface FieldDefinition {
|
||||
// 字段名称
|
||||
prop: string;
|
||||
@@ -310,6 +314,8 @@ function changeCategory(category: any) {
|
||||
description-key="description"
|
||||
:data="pageList"
|
||||
:actions="actions"
|
||||
tag-field="collectionType"
|
||||
:tag-map="collectionTypeLabelMap"
|
||||
/>
|
||||
</template>
|
||||
</PageData>
|
||||
|
||||
@@ -68,6 +68,7 @@ const vecotrDatabaseList = ref<any>([
|
||||
]);
|
||||
|
||||
const defaultEntity = {
|
||||
collectionType: 'DOCUMENT',
|
||||
alias: '',
|
||||
deptId: '',
|
||||
icon: '',
|
||||
@@ -108,6 +109,9 @@ const entity = ref<any>(normalizeEntity(defaultEntity));
|
||||
|
||||
const btnLoading = ref(false);
|
||||
const rules = ref({
|
||||
collectionType: [
|
||||
{ required: true, message: $t('message.required'), trigger: 'change' },
|
||||
],
|
||||
deptId: [
|
||||
{ required: true, message: $t('message.required'), trigger: 'blur' },
|
||||
],
|
||||
@@ -131,6 +135,16 @@ const rules = ref({
|
||||
{ required: true, message: $t('message.required'), trigger: 'blur' },
|
||||
],
|
||||
});
|
||||
const collectionTypeList = [
|
||||
{
|
||||
label: $t('documentCollection.collectionTypeDocument'),
|
||||
value: 'DOCUMENT',
|
||||
},
|
||||
{
|
||||
label: $t('documentCollection.collectionTypeFaq'),
|
||||
value: 'FAQ',
|
||||
},
|
||||
];
|
||||
|
||||
function openDialog(row: any = {}) {
|
||||
if (row.id) {
|
||||
@@ -217,6 +231,19 @@ defineExpose({
|
||||
:placeholder="$t('documentCollection.placeholder.title')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
prop="collectionType"
|
||||
:label="$t('documentCollection.collectionType')"
|
||||
>
|
||||
<ElSelect v-model="entity.collectionType">
|
||||
<ElOption
|
||||
v-for="item in collectionTypeList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
prop="categoryId"
|
||||
:label="$t('documentCollection.categoryId')"
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
<script setup lang="ts">
|
||||
import type {IDomEditor} from '@wangeditor/editor';
|
||||
|
||||
import {onBeforeUnmount, ref, shallowRef, watch} from 'vue';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
|
||||
import {ElButton, ElDialog, ElForm, ElFormItem, ElInput, ElMessage} from 'element-plus';
|
||||
import DOMPurify from 'dompurify';
|
||||
import {Editor, Toolbar} from '@wangeditor/editor-for-vue';
|
||||
import '@wangeditor/editor/dist/css/style.css';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
data: {
|
||||
type: Object as any,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['submit', 'update:modelValue']);
|
||||
|
||||
const editorRef = shallowRef<IDomEditor | null>(null);
|
||||
const form = ref<any>({
|
||||
id: '',
|
||||
collectionId: '',
|
||||
question: '',
|
||||
answerHtml: '',
|
||||
orderNo: 0,
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newData: any) => {
|
||||
form.value = {
|
||||
id: newData?.id || '',
|
||||
collectionId: newData?.collectionId || '',
|
||||
question: newData?.question || '',
|
||||
answerHtml: newData?.answerHtml || '',
|
||||
orderNo: newData?.orderNo ?? 0,
|
||||
};
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
const toolbarConfig = {
|
||||
excludeKeys: [
|
||||
'uploadImage',
|
||||
'insertImage',
|
||||
'group-image',
|
||||
'insertVideo',
|
||||
'group-video',
|
||||
'uploadVideo',
|
||||
'todo',
|
||||
'emotion',
|
||||
],
|
||||
};
|
||||
const editorConfig = {
|
||||
placeholder: $t('documentCollection.faq.answerPlaceholder'),
|
||||
};
|
||||
|
||||
const handleEditorCreated = (editor: IDomEditor) => {
|
||||
editorRef.value = editor;
|
||||
};
|
||||
|
||||
const closeDialog = () => {
|
||||
emit('update:modelValue', false);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!form.value.question?.trim()) {
|
||||
ElMessage.error($t('documentCollection.faq.questionRequired'));
|
||||
return;
|
||||
}
|
||||
const sanitizedHtml = DOMPurify.sanitize(form.value.answerHtml || '');
|
||||
const pureText = sanitizedHtml.replace(/<[^>]*>/g, '').trim();
|
||||
if (!pureText) {
|
||||
ElMessage.error($t('documentCollection.faq.answerRequired'));
|
||||
return;
|
||||
}
|
||||
emit('submit', {
|
||||
...form.value,
|
||||
question: form.value.question.trim(),
|
||||
answerHtml: sanitizedHtml,
|
||||
orderNo: Number(form.value.orderNo) || 0,
|
||||
});
|
||||
};
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value;
|
||||
if (editor) {
|
||||
editor.destroy();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
class="faq-edit-dialog"
|
||||
:model-value="modelValue"
|
||||
:title="form.id ? $t('button.edit') : $t('button.add')"
|
||||
width="min(920px, 92vw)"
|
||||
:close-on-click-modal="false"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<ElForm class="faq-form" label-position="top">
|
||||
<ElFormItem :label="$t('documentCollection.faq.question')">
|
||||
<ElInput
|
||||
v-model="form.question"
|
||||
:placeholder="$t('documentCollection.faq.questionPlaceholder')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem :label="$t('documentCollection.faq.answer')">
|
||||
<div class="editor-wrapper">
|
||||
<Toolbar
|
||||
:editor="editorRef"
|
||||
:default-config="toolbarConfig"
|
||||
mode="default"
|
||||
/>
|
||||
<Editor
|
||||
v-model="form.answerHtml"
|
||||
:default-config="editorConfig"
|
||||
mode="default"
|
||||
@on-created="handleEditorCreated"
|
||||
/>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton class="footer-btn" @click="closeDialog">{{ $t('button.cancel') }}</ElButton>
|
||||
<ElButton class="footer-btn" type="primary" @click="handleSubmit">
|
||||
{{ $t('button.save') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.faq-form :deep(.el-form-item__label) {
|
||||
padding-bottom: 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.editor-wrapper {
|
||||
width: 100%;
|
||||
border: 1px solid var(--el-border-color-light);
|
||||
border-radius: 10px;
|
||||
background: var(--el-fill-color-blank);
|
||||
overflow: hidden;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.editor-wrapper:focus-within {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
:deep(.w-e-toolbar) {
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
background: var(--el-fill-color-blank);
|
||||
}
|
||||
|
||||
:deep(.w-e-text-container) {
|
||||
min-height: 320px;
|
||||
background: var(--el-fill-color-blank);
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.footer-btn {
|
||||
min-width: 88px;
|
||||
}
|
||||
|
||||
:deep(.faq-edit-dialog .el-dialog) {
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.faq-edit-dialog .el-dialog__header) {
|
||||
margin-right: 0;
|
||||
padding: 18px 22px;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
}
|
||||
|
||||
:deep(.faq-edit-dialog .el-dialog__body) {
|
||||
padding: 18px 22px 16px;
|
||||
}
|
||||
|
||||
:deep(.faq-edit-dialog .el-dialog__footer) {
|
||||
padding: 12px 22px 18px;
|
||||
border-top: 1px solid var(--el-border-color-lighter);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,181 @@
|
||||
<script setup lang="ts">
|
||||
import {ref} from 'vue';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
|
||||
import {Delete, Edit, Plus} from '@element-plus/icons-vue';
|
||||
import {ElButton, ElMessage, ElMessageBox, ElTable, ElTableColumn,} from 'element-plus';
|
||||
|
||||
import {api} from '#/api/request';
|
||||
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
|
||||
import PageData from '#/components/page/PageData.vue';
|
||||
|
||||
import FaqEditDialog from './FaqEditDialog.vue';
|
||||
|
||||
const props = defineProps({
|
||||
knowledgeId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const pageDataRef = ref();
|
||||
const dialogVisible = ref(false);
|
||||
const editData = ref<any>({});
|
||||
const queryParams = ref({
|
||||
collectionId: props.knowledgeId,
|
||||
});
|
||||
const headerButtons = [
|
||||
{
|
||||
key: 'add',
|
||||
text: $t('button.add'),
|
||||
icon: Plus,
|
||||
type: 'primary',
|
||||
},
|
||||
];
|
||||
|
||||
const reloadList = () => {
|
||||
pageDataRef.value.setQuery(queryParams.value);
|
||||
};
|
||||
|
||||
const handleSearch = (keyword: string) => {
|
||||
pageDataRef.value.setQuery({
|
||||
...queryParams.value,
|
||||
question: keyword,
|
||||
});
|
||||
};
|
||||
|
||||
const openAddDialog = () => {
|
||||
editData.value = {
|
||||
collectionId: props.knowledgeId,
|
||||
answerHtml: '',
|
||||
question: '',
|
||||
};
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
const handleButtonClick = (event: any) => {
|
||||
if (event.key === 'add') {
|
||||
openAddDialog();
|
||||
}
|
||||
};
|
||||
|
||||
const openEditDialog = (row: any) => {
|
||||
editData.value = {
|
||||
id: row.id,
|
||||
collectionId: row.collectionId,
|
||||
question: row.question,
|
||||
answerHtml: row.answerHtml,
|
||||
orderNo: row.orderNo,
|
||||
};
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
const saveFaq = async (payload: any) => {
|
||||
const url = payload.id ? '/api/v1/faqItem/update' : '/api/v1/faqItem/save';
|
||||
const res = await api.post(url, payload);
|
||||
if (res.errorCode === 0) {
|
||||
ElMessage.success(payload.id ? $t('message.updateOkMessage') : $t('message.saveOkMessage'));
|
||||
dialogVisible.value = false;
|
||||
reloadList();
|
||||
} else {
|
||||
ElMessage.error(res.message);
|
||||
}
|
||||
};
|
||||
|
||||
const removeFaq = (row: any) => {
|
||||
ElMessageBox.confirm($t('message.deleteAlert'), $t('message.noticeTitle'), {
|
||||
confirmButtonText: $t('button.confirm'),
|
||||
cancelButtonText: $t('button.cancel'),
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
api.post('/api/v1/faqItem/remove', { id: row.id }).then((res) => {
|
||||
if (res.errorCode === 0) {
|
||||
ElMessage.success($t('message.deleteOkMessage'));
|
||||
reloadList();
|
||||
} else {
|
||||
ElMessage.error(res.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="faq-table-wrapper">
|
||||
<div class="faq-header">
|
||||
<HeaderSearch
|
||||
:buttons="headerButtons"
|
||||
@search="handleSearch"
|
||||
@button-click="handleButtonClick"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<PageData
|
||||
ref="pageDataRef"
|
||||
page-url="/api/v1/faqItem/page"
|
||||
:page-size="10"
|
||||
:extra-query-params="queryParams"
|
||||
>
|
||||
<template #default="{ pageList }">
|
||||
<ElTable :data="pageList" size="large">
|
||||
<ElTableColumn
|
||||
prop="question"
|
||||
:label="$t('documentCollection.faq.question')"
|
||||
min-width="220"
|
||||
/>
|
||||
<ElTableColumn
|
||||
prop="answerText"
|
||||
:label="$t('documentCollection.faq.answer')"
|
||||
min-width="260"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<ElTableColumn :label="$t('common.handle')" width="170" align="right">
|
||||
<template #default="{ row }">
|
||||
<ElButton link type="primary" :icon="Edit" @click="openEditDialog(row)">
|
||||
{{ $t('button.edit') }}
|
||||
</ElButton>
|
||||
<ElButton link type="danger" :icon="Delete" @click="removeFaq(row)">
|
||||
{{ $t('button.delete') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</ElTable>
|
||||
</template>
|
||||
</PageData>
|
||||
|
||||
<FaqEditDialog
|
||||
v-model="dialogVisible"
|
||||
:data="editData"
|
||||
@submit="saveFaq"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.faq-table-wrapper {
|
||||
width: 100%;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 12px;
|
||||
padding: 14px 16px 8px;
|
||||
background: var(--el-fill-color-blank);
|
||||
}
|
||||
|
||||
.faq-header {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-table th.el-table__cell) {
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
:deep(.el-table td.el-table__cell) {
|
||||
padding-top: 14px;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user