文章目录

  • 一、前言
  • 二、效果
  • 三、编码过程
    • 1.前端:
      • index.vue
      • projectShow.js
      • 富文本框: Editor/index.vue
      • 图片上传:ImgUploadCropper/index.vue
    • 2.后端:
      • 实体ProjectShow
      • ProjectShowController
      • IProjectShowService
      • ProjectShowServiceImpl
      • ProjectShowMapper
      • ProjectShowMapper.xml

一、前言

现在的需求是:实现一个项目展示模块,后端管理页面除了需要基础信息外,要加上一个图片上传和富文本框编辑器功能

二、效果


点击”图片存储地址”:可上传电脑任何位置的图片,并可对图片进行放大,缩小,和旋转。



存入数据库的图片以url地址存放

url直接百度可看到图片:

三、编码过程

1.前端:

index.vue

<template><div class="app-container"><!-- 新增项目 --><el-row :gutter="10" class="mb8"><el-col :span="1.5"><el-buttontype="primary"plainicon="el-icon-plus"size="mini"@click="handleAdd">新增</el-button></el-col></el-row><!-- 添加或修改项目展示 --><el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body><el-form ref="formObj" :model="form" :rules="rules" label-width="120px" ><el-form-item label="项目名称" prop="projectName"><el-input v-model="form.projectName" placeholder="请输入项目名称" /></el-form-item><el-form-item label="项目类型" prop="projectType"><el-selectv-model="form.projectType"placeholder="请选择项目类型"style="width: 65%"><el-optionv-for="dict in projectTypeOptions":key="dict.dictValue":label="dict.dictLabel":value="dict.dictValue"></el-option></el-select></el-form-item><el-form-item prop="picUrl" label="图片存储地址"  required><div class="coverImg-upload" @click="showCoverImgCropper = true"><img v-if="form.picUrl" :src="form.picUrl" class="coverImg" /><i v-else class="el-icon-plus coverImg-upload-icon" /></div></el-form-item><el-form-item prop="projectDetail" label="项目详情"><my-quill-editor v-model="form.projectDetail" ref="quillEditor" /></el-form-item><el-form-item label="备注" prop="remark"><el-inputv-model="form.remark"type="textarea"placeholder="请输入备注"/></el-form-item></el-form><img-upload-cropper:visible.sync="showCoverImgCropper"@upload-success="onCoverImgUploaded"/><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitForm">确 定</el-button><el-button @click="cancel">取 消</el-button></div></el-dialog><!-- 项目展示平台查询 --><el-tablev-loading="loading":data="projectShowList"row-key="id"default-expand-all:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"><el-table-column label="项目名称" align="center" prop="projectName" /><el-table-columnlabel="图片存储地址"align="center"prop="picUrl"v-if="false"/><el-table-columnlabel="项目详情"align="center"prop="projectDetail"v-if="false"/><el-table-columnlabel="项目类型"align="center"prop="projectType":formatter="projectTypeFormat"/><el-table-column label="创建人" align="center" prop="createUser" /><el-table-column label="创建时间" align="center" prop="createTime" /><el-table-column label="修改人" align="center" prop="updateUser" /><el-table-column label="修改时间" align="center" prop="updateTime" /><el-table-column label="备注" align="center" prop="remark"/><el-table-columnlabel="操作"align="center"class-name="small-padding fixed-width"><template slot-scope="scope"><el-buttonsize="mini"type="text"icon="el-icon-edit"@click="handleUpdate(scope.row)">修改</el-button><el-buttonsize="mini"type="text"icon="el-icon-delete"@click="handleDelete(scope.row)">删除</el-button></template></el-table-column></el-table></div>
</template><script>import {listProjectShow,addProjectShow,updateProjectShow,getProjectShow,delProjectShow,
} from "@/api/projectShow/projectShow";
import myQuillEditor from "@/components/Editor";
import ImgUploadCropper from "@/components/ImgUploadCropper";export default {name: "cpsp",components: {myQuillEditor,ImgUploadCropper,},data() {return {// 遮罩层loading: true,// 资产分类表格数据projectShowList: [],//计费方式字典projectTypeOptions: [],// 弹出层标题title: "",// 资产分类树选项categoryOptions: [],// 是否显示弹出层open: false,// 表单参数form: {id: null,projectName: null,projectType: "1",picUrl: "",projectDetail: "",remark: null,},showCoverImgCropper: false,formObj: "",// 表单校验rules: {projectName: [{ required: true, message: "项目名称不能为空", trigger: "blur" },],projectType: [{ required: true, message: "项目类型不能为空", trigger: "blur" },],picUrl: [{ required: true, trigger: "change", message: "图片存储地址不能为空" },],},};},mounted() {this.formObj = this.$refs.formObj;},created() {this.getList();this.getDicts("project_show_type").then((response) => {this.projectTypeOptions = response.data;});},methods: {/** 查询资产分类列表 */getList() {this.loading = true;listProjectShow(this.queryParams).then((response) => {this.projectShowList = response.data;this.loading = false;});},// 项目类型字典翻译projectTypeFormat(row, column) {return this.selectDictLabel(this.projectTypeOptions, row.projectType);},// 取消按钮cancel() {this.open = false;this.reset();},// 表单重置reset() {this.form = {id: null,projectName: null,projectType: "1",picUrl: "",projectDetail: "",remark: null,};this.resetForm("formObj");},/** 新增按钮操作 */handleAdd() {this.reset();this.open = true;this.title = "添加项目";},/*** 组件封面图片上传*/onCoverImgUploaded(picUrl) {this.form.picUrl = picUrl;// 清除表单校验红字this.formObj.clearValidate("picUrl");},/** 提交按钮 */submitForm() {this.$refs["formObj"].validate((valid) => {if (valid) {if (this.form.id != null) {updateProjectShow(this.form).then((response) => {this.msgSuccess("修改成功");this.open = false;this.getList();});} else {addProjectShow(this.form).then((response) => {this.msgSuccess("新增成功");this.open = false;this.getList();console.log(this.form);});}}});},/** 修改按钮操作 */handleUpdate(row) {this.reset();getProjectShow(row.id).then((response) => {this.form = response.data;this.open = true;this.title = "修改项目展示内容";});},/** 删除按钮操作 */handleDelete(row) {this.$confirm('是否确认删除项目名为"' + row.projectName + '"的数据项?', "警告", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(function () {return delProjectShow(row.id);}).then(() => {this.getList();this.msgSuccess("删除成功");});},},
};</script>
<style lang="scss">.coverImg-upload {margin-top: 10px;width: 150px;height: 150px;border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;img {width: 100%;height: 100%;}.coverImg-upload-icon {font-size: 28px;color: #8c939d;width: 150px;height: 150px;line-height: 150px;text-align: center;}}</style>

projectShow.js

import request from '@/utils/request'// 查询项目展示列表
export function listProjectShow(query) {return request({url: '/projectShow/list',method: 'get',params: query})
}
// 新增项目展示
export function addProjectShow(data) {return request({url: '/projectShow',method: 'post',data: data})
}// 修改项目展示
export function updateProjectShow(data) {return request({url: '/projectShow',method: 'put',data: data})
}
// 点击修改按钮获取到具体cpsp项目的详情
export function getProjectShow(id) {return request({url: '/projectShow/' + id,method: 'get'})
}// 删除资产分类
export function delProjectShow(id) {return request({url: '/projectShow/' + id,method: 'delete'})
}

富文本框: Editor/index.vue

<template><div><!-- 图片上传组件辅助 --><el-uploadclass="avatar-uploader quill-img":action="uploadImgUrl"name="file":headers="headers":show-file-list="false":on-success="quillImgSuccess":on-error="uploadError":before-upload="quillImgBefore"accept='.jpg,.jpeg,.png,.gif'></el-upload><!-- 富文本组件 --><quill-editorclass="editor"v-model="content"ref="quillEditor":options="editorOption"@blur="onEditorBlur($event)"@focus="onEditorFocus($event)"@change="onEditorChange($event)"></quill-editor></div>
</template><script>import { getToken } from '@/utils/auth'// 工具栏配置
const toolbarOptions = [["bold", "italic", "underline", "strike"],       // 加粗 斜体 下划线 删除线["blockquote", "code-block"],                    // 引用  代码块[{ list: "ordered" }, { list: "bullet" }],       // 有序、无序列表[{ indent: "-1" }, { indent: "+1" }],            // 缩进[{ size: ["small", false, "large", "huge"] }],   // 字体大小[{ header: [1, 2, 3, 4, 5, 6, false] }],         // 标题[{ color: [] }, { background: [] }],             // 字体颜色、字体背景颜色[{ align: [] }],                                 // 对齐方式["clean"],                                       // 清除文本格式["link", "image", "video"]                       // 链接、图片、视频
];import { quillEditor } from "vue-quill-editor";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";export default {model: {prop: "value",event: "change"},props: {/* 编辑器的内容 */value: {type: String},/* 图片大小 */maxSize: {type: Number,default: 4000 //kb}},components: { quillEditor },data() {return {content: this.value,editorOption: {placeholder: "",theme: "snow", // or 'bubble'placeholder: "请输入内容",modules: {toolbar: {container: toolbarOptions,handlers: {image: function(value) {if (value) {// 触发input框选择图片文件document.querySelector(".quill-img input").click();} else {this.quill.format("image", false);}}}}}},// uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址uploadImgUrl: process.env.VUE_APP_BASE_API + "/system/file/upload",headers: {Authorization: 'Bearer ' + getToken()}};},watch: {value: function() {this.content = this.value;}},methods: {onEditorBlur() {//失去焦点事件},onEditorFocus() {//获得焦点事件},onEditorChange() {//内容改变事件this.$emit("change", this.content);},// 富文本图片上传前quillImgBefore(file) {let fileType = file.type;if(fileType === 'image/jpeg' || fileType === 'image/png'){return true;}else {this.$message.error('请插入图片类型文件(jpg/jpeg/png)');return false;}},quillImgSuccess(res, file) {// res为图片服务器返回的数据// 获取富文本组件实例let quill = this.$refs.quillEditor.quill;// 如果上传成功if (res.code == 200) {// 获取光标所在位置let length = quill.getSelection().index;// 插入图片  res.url为服务器返回的图片地址quill.insertEmbed(length, "image", res.url);// 调整光标到最后quill.setSelection(length + 1);} else {this.$message.error("图片插入失败");}},// 富文本图片上传失败uploadError() {// loading动画消失this.$message.error("图片插入失败");}}
};</script> <style>.editor {line-height: normal !important;/* height: 192px; */
}
.quill-img {display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {border-right: 0px;content: "保存";padding-right: 0px;
}.ql-snow .ql-tooltip[data-mode="video"]::before {content: "请输入视频地址:";
}.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {content: "32px";
}.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {content: "标题6";
}.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {content: "等宽字体";
}</style>

图片上传:ImgUploadCropper/index.vue

<template><el-dialogclass="img-upload-cropper":title="title":visible.sync="show"width="800px"append-to-body@close="onDialogClose"><el-row><el-col :xs="24" :md="12" :style="{ height: '350px' }"><vue-cropperref="cropper":img="options.img"outputType="png":info="true":autoCrop="options.autoCrop":autoCropWidth="options.autoCropWidth":autoCropHeight="options.autoCropHeight":fixedBox="options.fixedBox"@realTime="realTime"/></el-col><el-col :xs="24" :md="12" :style="{ height: '350px' }"><divclass="upload-preview":style="`width:${options.autoCropWidth}px;height:${options.autoCropHeight}px;border-radius:${previewBorderRaidus}`"><img :src="previews.url" :style="previews.img" /></div></el-col></el-row><br /><el-row><el-col :lg="2" :md="2"><el-uploadaction="#":http-request="httpRequest":show-file-list="false":before-upload="beforeUpload"><el-button size="small">上传<i class="el-icon-upload el-icon--right"></i></el-button></el-upload></el-col><el-col :lg="{ span: 1, offset: 2 }" :md="2"><el-buttonicon="el-icon-plus"size="small"@click="changeScale(1)"></el-button></el-col><el-col :lg="{ span: 1, offset: 1 }" :md="2"><el-buttonicon="el-icon-minus"size="small"@click="changeScale(-1)"></el-button></el-col><el-col :lg="{ span: 1, offset: 1 }" :md="2"><el-buttonicon="el-icon-refresh-left"size="small"@click="rotateLeft()"></el-button></el-col><el-col :lg="{ span: 1, offset: 1 }" :md="2"><el-buttonicon="el-icon-refresh-right"size="small"@click="rotateRight()"></el-button></el-col><el-col :lg="{ span: 2, offset: 6 }" :md="2"><el-button type="primary" size="small" @click="uploadImg()">提 交</el-button></el-col></el-row></el-dialog>
</template><script>import { VueCropper } from "vue-cropper";
import { fileUpload } from "@/api/system/upload";
import { uploadAvatar } from "@/api/system/user";export default {name: "img-upload-cropper",components: { VueCropper },props: {visible: {type: Boolean,default: false,},title: {type: String,default: "",},compType: {type: String,default: "",},/*** 右边预览图的border-radius,单位自定*/previewBorderRaidus: {type: String,default: "",},},computed: {},watch: {visible(val) {this.show = val;},},data() {return {options: {img: "", //裁剪图片的地址autoCrop: true, // 是否默认生成截图框autoCropWidth: 200, // 默认生成截图框宽度autoCropHeight: 200, // 默认生成截图框高度fixedBox: true, // 固定截图框大小 不允许改变},show: false,previews: {},};},created() {},mounted() {},methods: {/*** 关闭时*/onDialogClose() {this.$emit("update:visible", false);},/*** 图片上传之前*/beforeUpload(file) {if (file.type.indexOf("image/") == -1) {this.msgError("文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。");} else {const reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => {this.options.img = reader.result;};}},/*** 上传到服务器*/uploadImg() {this.$refs.cropper.getCropBlob((data) => {let formData = new FormData();if (this.compType === "avatar") {// 头像上传formData.append("avatarfile", data);uploadAvatar(formData).then((response) => {console.log("												

若依框架图片上传、富文本框编辑器功能相关推荐

  1. ckeditor5 图片上传,tp5整合ckeditor5编辑器使用

    ** 更新:2019年1月29,"ckeditor5 图片上传,tp5整合ckeditor5编辑器使用"之前放的ckeditor.js文件过期,现已更新可用,同时提供可下载的cke ...

  2. iOS学习:调用相机,选择图片上传,带预览功能

    iOS学习:调用相机,选择图片上传,带预览功能 发表于2年前(2013-05-30 21:38)   阅读( 18194) | 评论( 16) 27人收藏此文章,我要收藏 赞3 8月22日珠海 OSC ...

  3. layui图片上传增加删除图标以及功能

    layui图片上传组件是没有删除功能的,这里自己增加删除功能: //删除图标var imgX = document.createElement("img"); imgX.src = ...

  4. 小程序自定义上传富文本并预览

    上传时的效果 预览时的效果 代码如下(可直接全部复制查看,注意:下面上传的接口需要改成你们自己的服务器上传接口) <view class="col"><text& ...

  5. GUNS框架图片上传详解

    1.html页面中的图片上传标签 2.对应html的js文件中 注意:只要保证上述图片三处红框跟定义的实体属性名保持一致即可.后台就可以拿到数据. 3.GUNS自定义avatar.tag标签 4.GU ...

  6. ssm框架图片上传与显示_SSM在线考试系统

    SSM在线考试系统,简称exam,它是一套基于SpringBoot+SSM+SpringSecurity技术开发的系统. 该系统分为前端和后端,前端学生可以进行测试,后端是数据的维护端.前端技术采用B ...

  7. wordpress框架图片上传

    以下方法为form提交至本页面,html+php混写. <form method="post" enctype="multipart/form-data" ...

  8. tornado框架图片上传和展示

    1.后端代码 import os import tornado.ioloop import tornado.web # web应用apifrom PIL import Imageclass Forms ...

  9. java ueditor 图片上传加水印_Ueditor编辑器上传图片加水印【亲测可用】-帝国CMS整合...

    Ueditor编辑器上传图片加水印 百度一下,有很多,但是方法都是一样的,写的不清不楚的.对于代码不是很了解的我们,却是头大.我整理了一下,下载下面的压缩包,解压缩之后,直接上传到  ueditor ...

最新文章

  1. Java多线程——多线程的基本概念和使用
  2. 网络嗅探混杂模式与非混杂模式的区别
  3. 北京租房一个月多少钱?数据带你了解北京8月各区租金情况
  4. 2008年第四季度开发者Top 100 Blogs
  5. 关于在centos下安装python3.7.0以上版本时报错ModuleNotFoundError No module named _ctypes 的解决办法
  6. 这才是真正的Git——Git内部原理揭秘!
  7. Django之 RESTful规范
  8. beautifulsoup获取属性_Python爬虫常用模块:BeautifulSoup
  9. 认识计算机硬件实验项目,实验1 认识计算机的硬件与硬件组装
  10. 使用Python实现一个简单的接口服务
  11. win10如何查看文件夹的大小 - 方法大全
  12. CSS3 移动端开发技巧
  13. js实现小时钟,js中Date对象的使用?
  14. matlab上机操作作业指导书,LED自动固晶基本操作1
  15. 2018Oracle11g下载与安装菜鸟教程(一)
  16. 标准MIDI文件格式
  17. 关系代数中的除法运算
  18. docker应用篇(1):如何搭建VXXXN
  19. Python练习册(二)
  20. 中层管理者如何做好员工管理

热门文章

  1. 饿了么联盟在哪里申请物料
  2. H264系列(7):H.264与MPEG4区别
  3. 挺带劲!这款开源数据库迁移工具超牛逼
  4. html鼠标移入显示图片动画,HTML5+CSS3鼠标移入移出图片生成随机动画_html/css_WEB-ITnose...
  5. 星际战甲服务器维护时间,星际战甲 官网:2月4日服务器维护结束公告
  6. python pil grab screen
  7. 抖音高贵气质的签名_这些抖音直播注意事项,不注意很可能被封号!
  8. 利用shell遍历文件夹下所有文件
  9. VS2008下水晶报表之简单示例
  10. HyperLynx(三十)高速串行总线仿真(二)