创建了新增+修改二合一页面,写完了新增相关代码,待测试

This commit is contained in:
高子兴 2024-07-04 00:45:37 +08:00
parent e88d034f4a
commit 06cada8109

View File

@ -0,0 +1,483 @@
<script setup>
import {onMounted, ref} from 'vue';
import {ElButton, ElForm, ElFormItem, ElInput, ElMessage, ElOption, ElSelect, ElUpload} from 'element-plus';
import {
AccessibilityHelp,
Alignment,
Autoformat,
AutoLink,
Autosave,
BalloonToolbar,
BlockQuote,
Bold,
ClassicEditor,
CodeBlock,
Essentials,
FindAndReplace,
GeneralHtmlSupport,
Heading,
HorizontalLine,
Indent,
IndentBlock,
Italic,
Link,
Paragraph,
SelectAll,
Style,
Table,
TableCaption,
TableCellProperties,
TableColumnResize,
TableProperties,
TableToolbar,
TextTransformation,
Undo
} from 'ckeditor5';
import translations from 'ckeditor5/translations/zh-cn.js';
import 'ckeditor5/ckeditor5.css';
import {Delete, Plus, Refresh, ZoomIn} from "@element-plus/icons-vue";
import {useRoute, useRouter} from "vue-router";
import axios from "axios";
const route = useRoute();
const router = useRouter();
const form = ref({
title: '',
author: '',
content: '',
summary: '',
tenant: '',
imagePath: ''
});
const createMode = ref(false);
const modeTitle = ref('');
const fileList = ref([]); //
const basePath = '/api/news'
const uploadUrl = basePath + '/uploadPic'; //
const dialogImageUrl = ref('');
const dialogVisible = ref(false); //
const beforeUpload = (file) => {
// png, jpg, jpeg
const isImage = file.type === 'image/png' || file.type === 'image/jpg' || file.type === 'image/jpeg';
if (!isImage) {
ElMessage.error('只能上传 png/jpg/jpeg 格式的图片文件!');
return false;
}
// 5MB
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isLt5M) {
ElMessage.error('上传文件大小不能超过 5MB');
return false;
}
return true;
};
const handleSuccess = (response, file, fileList) => {
file.url = response.url;
};
const handleError = (error, file, fileList) => {
ElMessage.error('图片上传失败,请重试!');
};
const handleChange = (file, fileList) => {
//
if (fileList.length > 1) {
fileList.splice(0, fileList.length - 1)
}
};
const handlePictureCardPreview = (file) => {
dialogImageUrl.value = file.url
dialogVisible.value = true
}
const handleRemove = (file) => {
fileList.value = fileList.value.filter((item) => item.uid !== file.uid);
console.log(file)
}
const handleCommit = async () => {
if (createMode.value) {
try {
form.value.imagePath = fileList.value[0].url;
await axios.post(basePath, form.value);
ElMessage.success('添加成功!');
router.push('/news');
} catch (e) {
ElMessage.error('添加失败,请重试!');
}
} else {
try {
const res = await axios.put(basePath, form.value);
ElMessage.success('修改成功!');
router.push('/news');
} catch (e) {
ElMessage.error('修改失败,请重试!');
}
}
};
const isLayoutReady = ref(false);
const config = ref(null); // CKEditor needs the DOM tree before calculating the configuration.
const editor = ClassicEditor;
onMounted(() => {
if (route.query.mode === 'create') {
createMode.value = true;
modeTitle.value = '添加资讯';
}
if (route.query.mode === 'edit') {
createMode.value = false;
modeTitle.value = '修改资讯';
fetchNewsDetail();
}
config.value = {
toolbar: {
items: [
'undo',
'redo',
'|',
'heading',
'style',
'|',
'bold',
'italic',
'|',
'link',
'insertTable',
'blockQuote',
'codeBlock',
'|',
'alignment',
'|',
'indent',
'outdent'
],
shouldNotGroupWhenFull: false
},
plugins: [
AccessibilityHelp,
Alignment,
Autoformat,
AutoLink,
Autosave,
BalloonToolbar,
BlockQuote,
Bold,
CodeBlock,
Essentials,
FindAndReplace,
GeneralHtmlSupport,
Heading,
HorizontalLine,
Indent,
IndentBlock,
Italic,
Link,
Paragraph,
SelectAll,
Style,
Table,
TableCaption,
TableCellProperties,
TableColumnResize,
TableProperties,
TableToolbar,
TextTransformation,
Undo
],
balloonToolbar: ['bold', 'italic', '|', 'link'],
heading: {
options: [
{
model: 'paragraph',
title: 'Paragraph',
class: 'ck-heading_paragraph'
},
{
model: 'heading1',
view: 'h1',
title: 'Heading 1',
class: 'ck-heading_heading1'
},
{
model: 'heading2',
view: 'h2',
title: 'Heading 2',
class: 'ck-heading_heading2'
},
{
model: 'heading3',
view: 'h3',
title: 'Heading 3',
class: 'ck-heading_heading3'
},
{
model: 'heading4',
view: 'h4',
title: 'Heading 4',
class: 'ck-heading_heading4'
},
{
model: 'heading5',
view: 'h5',
title: 'Heading 5',
class: 'ck-heading_heading5'
},
{
model: 'heading6',
view: 'h6',
title: 'Heading 6',
class: 'ck-heading_heading6'
}
]
},
htmlSupport: {
allow: [
{
name: /^.*$/,
styles: true,
attributes: true,
classes: true
}
]
},
initialData: '',
language: 'zh-cn',
link: {
addTargetToExternalLinks: true,
defaultProtocol: 'https://',
decorators: {
toggleDownloadable: {
mode: 'manual',
label: 'Downloadable',
attributes: {
download: 'file'
}
}
}
},
menuBar: {
isVisible: true
},
placeholder: '请在此处输入你的文章',
style: {
definitions: [
{
name: 'Article category',
element: 'h3',
classes: ['category']
},
{
name: 'Title',
element: 'h2',
classes: ['document-title']
},
{
name: 'Subtitle',
element: 'h3',
classes: ['document-subtitle']
},
{
name: 'Info box',
element: 'p',
classes: ['info-box']
},
{
name: 'Side quote',
element: 'blockquote',
classes: ['side-quote']
},
{
name: 'Marker',
element: 'span',
classes: ['marker']
},
{
name: 'Spoiler',
element: 'span',
classes: ['spoiler']
},
{
name: 'Code (dark)',
element: 'pre',
classes: ['fancy-code', 'fancy-code-dark']
},
{
name: 'Code (bright)',
element: 'pre',
classes: ['fancy-code', 'fancy-code-bright']
}
]
},
table: {
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties']
},
translations: [translations]
};
isLayoutReady.value = true;
});
</script>
<template>
<div class="form-container">
<el-form :model="form" label-width="120px">
<h2>{{ modeTitle }}</h2>
<el-form-item label="新闻标题">
<el-input v-model="form.title" placeholder="请输入新闻标题"></el-input>
</el-form-item>
<el-form-item label="新闻图片路径">
<el-upload
:action="uploadUrl"
:limit="2"
:before-upload="beforeUpload"
:on-success="handleSuccess"
:on-error="handleError"
:on-change="handleChange"
:file-list="fileList"
list-type="picture-card"
auto-upload
v-model:file-list="fileList"
>
<template #file="{ file }">
<div>
<img class="el-upload-list__item-thumbnail" :src="file.url" alt=""/>
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<el-icon><zoom-in/></el-icon>
</span>
<span
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<el-icon><Delete/></el-icon>
</span>
</span>
</div>
</template>
<el-icon v-if="fileList.length === 0">
<Plus/>
</el-icon>
<el-icon v-else>
<Refresh/>
</el-icon>
</el-upload>
<div class="tip">
请上传大小不超过 <span style="color: red;">5MB</span> 格式为 <span style="color: red;">png/jpg/jpeg</span> 的文件
</div>
</el-form-item>
<el-form-item label="新闻内容">
<div class="editor-container editor-container_classic-editor editor-container_include-style"
ref="editorContainerElement">
<div class="editor-container__editor">
<div ref="editorElement">
<ckeditor v-if="isLayoutReady" v-model="form.content" :editor="editor" :config="config"/>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="作者">
<el-input v-model="form.author" placeholder="请输入作者"></el-input>
</el-form-item>
<el-form-item label="新闻简介">
<el-input v-model="form.summary" placeholder="请输入新闻简介"></el-input>
</el-form-item>
<el-form-item label="选择租户">
<el-select v-model="form.tenant" placeholder="请选择" class="dynamic-width-select">
<el-option label="Option 1" value="option1"></el-option>
<el-option label="Option 2" value="option2"></el-option>
<el-option label="Option 3" value="option3"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">确定</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
<el-dialog v-model="dialogVisible" class="image-preview">
<img w-full :src="dialogImageUrl" alt="Preview Image"/>
</el-dialog>
</template>
<style scoped>
.form-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: white;
overflow-y: auto; /* 使容器在内容溢出时出现滚动条 */
}
.image-preview {
display: flex;
justify-content: center;
align-items: center;
}
.image-preview img {
max-width: 100%;
height: auto;
}
.tip {
margin-top: 8px;
color: #727272;
font-size: 12px;
}
.el-form {
background: white;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 55%;
max-height: 90vh; /* 确保表单不会超过视口高度 */
overflow-y: auto; /* 使表单在内容溢出时出现滚动条 */
}
.el-form-item {
margin-bottom: 1rem;
text-align: left;
}
.el-form-item label {
display: block;
margin-bottom: 0.5rem;
}
.el-input,
.el-select {
width: 100%;
}
.el-button--primary {
background-color: #007bff;
color: white;
}
.el-button--primary:hover {
background-color: #0056b3;
}
.dynamic-width-select {
min-width: 30%;
max-width: 100%;
width: auto; /* 使宽度根据内容调整 */
}
</style>