202 lines
4.6 KiB
Vue
202 lines
4.6 KiB
Vue
<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>
|