Browse Source

轮播图新增富文本

dev-V1.0.6
wangmingyong@163.com 3 months ago
parent
commit
834dd5eb62
  1. 10
      zdxt-web-client/zdxt-admin-plus-ui/src/router/index.ts
  2. 2
      zdxt-web-client/zdxt-admin-plus-ui/src/views/nos/add.vue
  3. 55
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/add.vue
  4. 33
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/detail.vue
  5. 92
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/edit.vue
  6. 2
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/add.vue
  7. 2
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/detail.vue
  8. 2
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/edit.vue
  9. 2
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/repost.vue

10
zdxt-web-client/zdxt-admin-plus-ui/src/router/index.ts

@ -185,7 +185,7 @@ export const constantRoutes: RouteRecordRaw[] = [
path: '', path: '',
component: () => import('@/views/supervision/educationServices/add.vue'), component: () => import('@/views/supervision/educationServices/add.vue'),
name: 'EducationServicesAdd', name: 'EducationServicesAdd',
meta: { title: '新增普法服务', icon: 'plus' } meta: { title: '新增涉企服务', icon: 'plus' }
} }
] ]
}, },
@ -198,7 +198,7 @@ export const constantRoutes: RouteRecordRaw[] = [
path: '', path: '',
component: () => import('@/views/supervision/educationServices/repost.vue'), component: () => import('@/views/supervision/educationServices/repost.vue'),
name: 'EducationServicesRepost', name: 'EducationServicesRepost',
meta: { title: '转载普法服务', icon: 'plus' } meta: { title: '转载涉企服务', icon: 'plus' }
} }
] ]
}, },
@ -211,7 +211,7 @@ export const constantRoutes: RouteRecordRaw[] = [
path: '', path: '',
component: () => import('@/views/supervision/educationServices/draft.vue'), component: () => import('@/views/supervision/educationServices/draft.vue'),
name: 'EducationServicesDraft', name: 'EducationServicesDraft',
meta: { title: '普法服务草稿箱', activeMenu: '/supervision/educationServices' } meta: { title: '涉企服务草稿箱', activeMenu: '/supervision/educationServices' }
} }
] ]
}, },
@ -224,7 +224,7 @@ export const constantRoutes: RouteRecordRaw[] = [
path: '', path: '',
component: () => import('@/views/supervision/educationServices/edit.vue'), component: () => import('@/views/supervision/educationServices/edit.vue'),
name: 'EducationServicesEdit', name: 'EducationServicesEdit',
meta: { title: '编辑普法服务', activeMenu: '/supervision/educationServices' } meta: { title: '编辑涉企服务', activeMenu: '/supervision/educationServices' }
} }
] ]
}, },
@ -237,7 +237,7 @@ export const constantRoutes: RouteRecordRaw[] = [
path: '', path: '',
component: () => import('@/views/supervision/educationServices/detail.vue'), component: () => import('@/views/supervision/educationServices/detail.vue'),
name: 'EducationServicesDetail', name: 'EducationServicesDetail',
meta: { title: '普法服务详情', activeMenu: '/supervision/educationServices' } meta: { title: '涉企服务详情', activeMenu: '/supervision/educationServices' }
} }
] ]
}, },

2
zdxt-web-client/zdxt-admin-plus-ui/src/views/nos/add.vue

@ -1,7 +1,7 @@
<template> <template>
<div class="add-carousel-container"> <div class="add-carousel-container">
<div class="page-header"> <div class="page-header">
<h1>新增普法服务</h1> <h1>新增涉企服务</h1>
</div> </div>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container"> <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container">

55
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/add.vue

@ -38,7 +38,17 @@
</el-form-item> </el-form-item>
<el-form-item v-else label="富文本内容:" prop="content"> <el-form-item v-else label="富文本内容:" prop="content">
<Editor v-model="form.content" :height="400" /> <div class="editor-wrapper">
<QuillEditor
ref="quillEditorRef"
v-model:content="form.content"
content-type="html"
:toolbar="toolbarOptions"
theme="snow"
class="quill-editor"
placeholder="请输入富文本内容"
/>
</div>
</el-form-item> </el-form-item>
<el-form-item label="轮播图:" prop="imageUrl"> <el-form-item label="轮播图:" prop="imageUrl">
@ -80,15 +90,17 @@ import { getCurrentInstance, onMounted, reactive, ref } from 'vue';
import type { ComponentInternalInstance } from 'vue'; import type { ComponentInternalInstance } from 'vue';
import type { FormRules, UploadRequestOptions } from 'element-plus'; import type { FormRules, UploadRequestOptions } from 'element-plus';
import { ElForm, ElMessage } from 'element-plus'; import { ElForm, ElMessage } from 'element-plus';
import { QuillEditor } from '@vueup/vue-quill';
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { addCarouselBanner } from '@/api/supervision/carouselBanner'; import { addCarouselBanner } from '@/api/supervision/carouselBanner';
import { getDicts } from '@/api/system/dict/data'; import { getDicts } from '@/api/system/dict/data';
import request from '@/utils/request'; import request from '@/utils/request';
import Editor from '@/components/Editor/index.vue';
const route = useRoute(); const route = useRoute();
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const formRef = ref<InstanceType<typeof ElForm>>(); const formRef = ref<InstanceType<typeof ElForm>>();
const quillEditorRef = ref<InstanceType<typeof QuillEditor>>();
const submitting = ref(false); const submitting = ref(false);
const platformOptions = ref<{ label: string; value: number }[]>([]); const platformOptions = ref<{ label: string; value: number }[]>([]);
@ -110,6 +122,20 @@ const typeOptions = [
{ label: '外部链接', value: 1 } { label: '外部链接', value: 1 }
]; ];
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ header: 1 }, { header: 2 }],
[{ list: 'ordered' }, { list: 'bullet' }],
[{ indent: '-1' }, { indent: '+1' }],
[{ size: ['small', false, 'large', 'huge'] }],
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }],
[{ align: [] }],
['link', 'image', 'video'],
['clean']
];
const form = reactive({ const form = reactive({
title: '', title: '',
targetPlatform: undefined as number | undefined, targetPlatform: undefined as number | undefined,
@ -194,6 +220,10 @@ const submitForm = async (status: number, successMessage: string) => {
const isValid = await formRef.value.validate().catch(() => false); const isValid = await formRef.value.validate().catch(() => false);
if (!isValid) return; if (!isValid) return;
if (form.type === 0 && quillEditorRef.value) {
form.content = quillEditorRef.value.getHTML?.() || form.content;
}
submitting.value = true; submitting.value = true;
try { try {
const res: any = await addCarouselBanner({ const res: any = await addCarouselBanner({
@ -294,6 +324,27 @@ onMounted(() => {
max-width: 500px; max-width: 500px;
} }
.editor-wrapper {
width: 100%;
max-width: 900px;
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
}
.quill-editor {
height: 500px;
}
:deep(.ql-container) {
min-height: 500px;
height: 100%;
}
:deep(.ql-editor) {
min-height: 450px;
}
.upload-area { .upload-area {
width: 100%; width: 100%;
max-width: 620px; max-width: 620px;

33
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/detail.vue

@ -9,15 +9,20 @@
<el-descriptions-item label="标题">{{ detail.title || '-' }}</el-descriptions-item> <el-descriptions-item label="标题">{{ detail.title || '-' }}</el-descriptions-item>
<el-descriptions-item label="内容发布在">{{ detail.targetPlatformLabel || '-' }}</el-descriptions-item> <el-descriptions-item label="内容发布在">{{ detail.targetPlatformLabel || '-' }}</el-descriptions-item>
<el-descriptions-item label="橱窗">{{ formatCarouselPosition(detail.carouselPosition) }}</el-descriptions-item> <el-descriptions-item label="橱窗">{{ formatCarouselPosition(detail.carouselPosition) }}</el-descriptions-item>
<el-descriptions-item label="类型">{{ formatType(detail.type) }}</el-descriptions-item>
<el-descriptions-item label="显示天数">{{ formatDisplayDays(detail.displayDays) }}</el-descriptions-item> <el-descriptions-item label="显示天数">{{ formatDisplayDays(detail.displayDays) }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ detail.statusLabel || formatStatus(detail.status) }}</el-descriptions-item> <el-descriptions-item label="状态">{{ detail.statusLabel || formatStatus(detail.status) }}</el-descriptions-item>
<el-descriptions-item label="发布时间">{{ detail.createTime || detail.updateTime || '-' }}</el-descriptions-item> <el-descriptions-item label="发布时间">{{ detail.createTime || detail.updateTime || '-' }}</el-descriptions-item>
<el-descriptions-item label="链接"> <el-descriptions-item v-if="detail.type === 1 || detail.type === undefined" label="链接">
<el-link v-if="detail.linkUrl" :href="detail.linkUrl" target="_blank" type="primary"> <el-link v-if="detail.linkUrl" :href="detail.linkUrl" target="_blank" type="primary">
{{ detail.linkUrl }} {{ detail.linkUrl }}
</el-link> </el-link>
<span v-else>-</span> <span v-else>-</span>
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item v-else label="富文本内容">
<div v-if="detail.content" class="rich-text-content" v-html="detail.content"></div>
<span v-else>-</span>
</el-descriptions-item>
</el-descriptions> </el-descriptions>
<div class="image-section"> <div class="image-section">
@ -53,12 +58,14 @@ const detail = reactive<any>({
title: '', title: '',
targetPlatformLabel: '', targetPlatformLabel: '',
carouselPosition: undefined, carouselPosition: undefined,
type: undefined as number | undefined,
displayDays: undefined, displayDays: undefined,
status: undefined, status: undefined,
statusLabel: '', statusLabel: '',
createTime: '', createTime: '',
updateTime: '', updateTime: '',
linkUrl: '', linkUrl: '',
content: '',
imageUrl: '' imageUrl: ''
}); });
@ -67,6 +74,12 @@ const formatCarouselPosition = (value?: number) => {
return `橱窗${value}`; return `橱窗${value}`;
}; };
const formatType = (value?: number) => {
if (value === 0) return '富文本';
if (value === 1) return '外部链接';
return '-';
};
const formatDisplayDays = (value?: number) => { const formatDisplayDays = (value?: number) => {
if (value === undefined || value === null) return '-'; if (value === undefined || value === null) return '-';
if (Number(value) === 0) return '永久'; if (Number(value) === 0) return '永久';
@ -173,6 +186,24 @@ onMounted(() => {
color: #909399; color: #909399;
} }
.rich-text-content {
max-width: 700px;
padding: 12px;
border: 1px solid #ebeef5;
border-radius: 4px;
background: #fafafa;
line-height: 1.6;
}
.rich-text-content :deep(img) {
max-width: 100%;
height: auto;
}
.rich-text-content :deep(p) {
margin: 8px 0;
}
.form-actions { .form-actions {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;

92
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/edit.vue

@ -21,16 +21,36 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="类型:" prop="type">
<el-select v-model="form.type" placeholder="请选择" class="form-select" @change="handleTypeChange">
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="显示天数:" prop="displayDays"> <el-form-item label="显示天数:" prop="displayDays">
<el-select v-model="form.displayDays" placeholder="请选择" class="form-select"> <el-select v-model="form.displayDays" placeholder="请选择" class="form-select">
<el-option v-for="item in displayDaysOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in displayDaysOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="链接:" prop="linkUrl"> <el-form-item v-if="form.type === 1" label="链接:" prop="linkUrl">
<el-input v-model="form.linkUrl" placeholder="请输入跳转链接" class="form-input" /> <el-input v-model="form.linkUrl" placeholder="请输入跳转链接" class="form-input" />
</el-form-item> </el-form-item>
<el-form-item v-else label="富文本内容:" prop="content">
<div class="editor-wrapper">
<QuillEditor
ref="quillEditorRef"
v-model:content="form.content"
content-type="html"
:toolbar="toolbarOptions"
theme="snow"
class="quill-editor"
placeholder="请输入富文本内容"
/>
</div>
</el-form-item>
<el-form-item label="轮播图:" prop="imageUrl"> <el-form-item label="轮播图:" prop="imageUrl">
<div class="upload-area"> <div class="upload-area">
<div class="upload-row"> <div class="upload-row">
@ -70,6 +90,8 @@ import { getCurrentInstance, onMounted, reactive, ref } from 'vue';
import type { ComponentInternalInstance } from 'vue'; import type { ComponentInternalInstance } from 'vue';
import type { FormRules, UploadRequestOptions } from 'element-plus'; import type { FormRules, UploadRequestOptions } from 'element-plus';
import { ElForm, ElMessage } from 'element-plus'; import { ElForm, ElMessage } from 'element-plus';
import { QuillEditor } from '@vueup/vue-quill';
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { editCarouselBanner, getCarouselBannerDetails } from '@/api/supervision/carouselBanner'; import { editCarouselBanner, getCarouselBannerDetails } from '@/api/supervision/carouselBanner';
import { getDicts } from '@/api/system/dict/data'; import { getDicts } from '@/api/system/dict/data';
@ -78,6 +100,7 @@ import request from '@/utils/request';
const route = useRoute(); const route = useRoute();
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const formRef = ref<InstanceType<typeof ElForm>>(); const formRef = ref<InstanceType<typeof ElForm>>();
const quillEditorRef = ref<InstanceType<typeof QuillEditor>>();
const pageLoading = ref(true); const pageLoading = ref(true);
const submitting = ref(false); const submitting = ref(false);
const recordId = ref(''); const recordId = ref('');
@ -96,27 +119,55 @@ const displayDaysOptions = [
{ label: '30天', value: 30 }, { label: '30天', value: 30 },
{ label: '永久', value: 0 } { label: '永久', value: 0 }
]; ];
const typeOptions = [
{ label: '富文本', value: 0 },
{ label: '外部链接', value: 1 }
];
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ header: 1 }, { header: 2 }],
[{ list: 'ordered' }, { list: 'bullet' }],
[{ indent: '-1' }, { indent: '+1' }],
[{ size: ['small', false, 'large', 'huge'] }],
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }],
[{ align: [] }],
['link', 'image', 'video'],
['clean']
];
const form = reactive({ const form = reactive({
title: '', title: '',
targetPlatform: undefined as number | undefined, targetPlatform: undefined as number | undefined,
carouselPosition: undefined as number | undefined, carouselPosition: undefined as number | undefined,
type: undefined as number | undefined,
displayDays: undefined as number | undefined, displayDays: undefined as number | undefined,
linkUrl: '', linkUrl: '',
content: '',
imageUrl: '', imageUrl: '',
status: 2, status: 2
type: 1
}); });
const rules: FormRules = { const rules: FormRules = {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }], title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
targetPlatform: [{ required: true, message: '请选择内容发布在', trigger: 'change' }], targetPlatform: [{ required: true, message: '请选择内容发布在', trigger: 'change' }],
carouselPosition: [{ required: true, message: '请选择橱窗', trigger: 'change' }], carouselPosition: [{ required: true, message: '请选择橱窗', trigger: 'change' }],
type: [{ required: true, message: '请选择类型', trigger: 'change' }],
displayDays: [{ required: true, message: '请选择显示天数', trigger: 'change' }], displayDays: [{ required: true, message: '请选择显示天数', trigger: 'change' }],
linkUrl: [{ required: true, message: '请输入链接', trigger: 'blur' }], linkUrl: [{ required: true, message: '请输入跳转链接', trigger: 'blur' }],
content: [{ required: true, message: '请输入富文本内容', trigger: 'blur' }],
imageUrl: [{ required: true, message: '请上传轮播图', trigger: 'change' }] imageUrl: [{ required: true, message: '请上传轮播图', trigger: 'change' }]
}; };
const handleTypeChange = () => {
form.linkUrl = '';
form.content = '';
formRef.value?.validateField('linkUrl');
formRef.value?.validateField('content');
};
const beforeImageUpload = (file: File) => { const beforeImageUpload = (file: File) => {
const isImage = ['image/jpeg', 'image/jpg', 'image/png'].includes(file.type); const isImage = ['image/jpeg', 'image/jpg', 'image/png'].includes(file.type);
const isLt5M = file.size / 1024 / 1024 < 5; const isLt5M = file.size / 1024 / 1024 < 5;
@ -175,6 +226,10 @@ const submitForm = async (status: number, successMessage: string) => {
const isValid = await formRef.value.validate().catch(() => false); const isValid = await formRef.value.validate().catch(() => false);
if (!isValid) return; if (!isValid) return;
if (form.type === 0 && quillEditorRef.value) {
form.content = quillEditorRef.value.getHTML?.() || form.content;
}
submitting.value = true; submitting.value = true;
try { try {
const res: any = await editCarouselBanner({ const res: any = await editCarouselBanner({
@ -182,11 +237,12 @@ const submitForm = async (status: number, successMessage: string) => {
title: form.title, title: form.title,
targetPlatform: form.targetPlatform, targetPlatform: form.targetPlatform,
carouselPosition: form.carouselPosition, carouselPosition: form.carouselPosition,
type: form.type,
displayDays: form.displayDays, displayDays: form.displayDays,
linkUrl: form.linkUrl, linkUrl: form.type === 1 ? form.linkUrl : undefined,
content: form.type === 0 ? form.content : undefined,
imageUrl: form.imageUrl, imageUrl: form.imageUrl,
// status, // status,
type: form.type,
// isDelete: status === 2 ? 0 : 1 // isDelete: status === 2 ? 0 : 1
}); });
if (res.code === 200) { if (res.code === 200) {
@ -232,11 +288,12 @@ const loadDetail = async () => {
form.title = data.title || ''; form.title = data.title || '';
form.targetPlatform = data.targetPlatform ?? undefined; form.targetPlatform = data.targetPlatform ?? undefined;
form.carouselPosition = data.carouselPosition ?? undefined; form.carouselPosition = data.carouselPosition ?? undefined;
form.type = data.type ?? undefined;
form.displayDays = data.displayDays ?? undefined; form.displayDays = data.displayDays ?? undefined;
form.linkUrl = data.linkUrl || ''; form.linkUrl = data.linkUrl || '';
form.content = data.content || '';
form.imageUrl = data.imageUrl || ''; form.imageUrl = data.imageUrl || '';
form.status = data.status ?? 2; form.status = data.status ?? 2;
form.type = data.type ?? 1;
} catch (error) { } catch (error) {
console.error('加载详情失败:', error); console.error('加载详情失败:', error);
ElMessage.error('加载详情失败'); ElMessage.error('加载详情失败');
@ -308,6 +365,27 @@ onMounted(async () => {
max-width: 500px; max-width: 500px;
} }
.editor-wrapper {
width: 100%;
max-width: 900px;
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
}
.quill-editor {
height: 500px;
}
:deep(.ql-container) {
min-height: 500px;
height: 100%;
}
:deep(.ql-editor) {
min-height: 450px;
}
.upload-area { .upload-area {
width: 100%; width: 100%;
max-width: 620px; max-width: 620px;

2
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/add.vue

@ -1,7 +1,7 @@
<template> <template>
<div class="add-carousel-container"> <div class="add-carousel-container">
<div class="page-header"> <div class="page-header">
<h1>新增普法服务</h1> <h1>新增涉企服务</h1>
</div> </div>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container"> <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container">

2
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/detail.vue

@ -1,7 +1,7 @@
<template> <template>
<div v-loading="pageLoading" class="detail-container"> <div v-loading="pageLoading" class="detail-container">
<div class="page-header"> <div class="page-header">
<h1>普法服务详情</h1> <h1>涉企服务详情</h1>
</div> </div>
<div class="detail-card"> <div class="detail-card">

2
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/edit.vue

@ -1,7 +1,7 @@
<template> <template>
<div v-loading="pageLoading" class="add-carousel-container"> <div v-loading="pageLoading" class="add-carousel-container">
<div class="page-header"> <div class="page-header">
<h1>编辑普法服务</h1> <h1>编辑涉企服务</h1>
</div> </div>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container"> <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container">

2
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/repost.vue

@ -1,7 +1,7 @@
<template> <template>
<div class="add-carousel-container"> <div class="add-carousel-container">
<div class="page-header"> <div class="page-header">
<h1>转载普法服务</h1> <h1>转载涉企服务</h1>
</div> </div>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container"> <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="form-container">

Loading…
Cancel
Save