当前位置:   article > 正文

基于vue实现的小程序管理后台图文编辑器

vue 管理后台 海报编辑器

附加说明:

1)基于element-ui的button和upload组件

2)支持文字和图片混合编辑

实现思路:

  页面中主要的组件:多行文本编辑框(高度随文本变化)、图片上传

       功能点梳理:

              新增段落,在文末或者任一段落上可点击添加段落按钮,点击后在文末或段落后新增一个段落;

              新增的段落可选择是文本还是图片,选择文本则将该新增段落变为多行文本编辑框,选择图片则触发选择本地文件进行上传,上传完后替换原新增段落;

              任一段落可进行上下移动、删除、在其下增加新增端口的操作;

              完成编辑,点击完成编辑按钮,用户可指定后续操作,一般是将编辑的内容保存到后端。

代码如下:

  1. <template>
  2. <div class="editor-viewer">
  3. <div class="content-viewer">
  4. <div class="content-list">
  5. <div v-for="(content, index) in contentList" class="editor-item"
  6. :key="index" :tabindex="index" @mouseover="handleMouseIn(index, content)"
  7. @mouseout="handleMouseOut(index, content)">
  8. <div class="textarea" contenteditable="true" v-if="content.type === 'text'" >
  9. {{content.value}}
  10. </div>
  11. <!-- <textarea v-if="content.type === 'text'" v-model="content.value"></textarea> -->
  12. <img v-if="content.type === 'image'" :src="content.value">
  13. <div class="add-module" v-if="content.type === 'empty'">
  14. <el-button @click="change2Text(index)">A</el-button>
  15. <el-upload :data="{index: index}"
  16. class="el-button"
  17. action="https://jsonplaceholder.typicode.com/posts/"
  18. :show-file-list="false"
  19. :on-success="handleUploadSuccess"
  20. :before-upload="beforeImageUpload" titlr="只能上传jpg/png文件,且不超过2M">
  21. <i class="el-icon-picture" ></i>
  22. </el-upload>
  23. <el-button @click="delOne(index)" icon="el-icon-delete"></el-button>
  24. </div>
  25. <div class="editor-item-ops" v-if="content.type !== 'empty' " v-show="content.visible">
  26. <el-button icon="el-icon-plus" circle @click="beginAdd(index)"></el-button>
  27. <el-button icon="el-icon-arrow-down" v-if="contentList.length > 1 && index !== contentList.length - 1"
  28. circle @click="moveDown(index)"></el-button>
  29. <el-button icon="el-icon-arrow-up" circle v-if="contentList.length > 1 && index !== 0"
  30. @click="moveUp(index)"></el-button>
  31. <el-button icon="el-icon-delete" circle @click="delOne(index, true)"></el-button>
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. <div class="editor-btn-viewer">
  37. <el-button class="editor-btn" icon="el-icon-circle-check-outline"
  38. @click="finishEdit"> 完成编辑</el-button>
  39. <el-button class="editor-btn" icon="el-icon-circle-plus-outline" @click="addAtLast"> 添加模块</el-button>
  40. </div>
  41. </div>
  42. </template>
  43. <script>
  44. import {Upload} from 'element-ui'
  45. export default {
  46. data () {
  47. return {
  48. contentList: []
  49. }
  50. },
  51. props: ['contents'],
  52. components: {
  53. ElUpload: Upload
  54. },
  55. methods: {
  56. spliceContent (start, count, added) {
  57. if (typeof added !== 'undefined') {
  58. return this.contentList.splice(start, count, added)
  59. } else {
  60. return this.contentList.splice(start, count)
  61. }
  62. },
  63. addAtLast () {
  64. this.contentList.push({type: 'empty', value: '', visible: false})
  65. },
  66. beginAdd (index) {
  67. this.spliceContent(index+1, 0, {type: 'empty', value: '', visible: false})
  68. },
  69. moveDown (index) {
  70. let cur = this.spliceContent(index, 1)
  71. this.spliceContent(index + 1, 0, cur[0])
  72. },
  73. moveUp (index) {
  74. let cur = this.spliceContent(index, 1)
  75. this.spliceContent(index - 1, 0, cur[0])
  76. },
  77. delOne (index, delImage = false) {
  78. this.spliceContent(index, 1)
  79. if (delImage) {
  80. // todo: 需要删除内容服务器上的图片文件
  81. }
  82. },
  83. change2Text (index) {
  84. this.spliceContent(index, 1, {type: 'text', value: '', visible: false})
  85. },
  86. change2Image (index) {
  87. this.spliceContent(index, 1, {type: 'image', value: '', visible: false})
  88. },
  89. handleUploadSuccess(res, file) {
  90. // res 需要返回附加data:index
  91. let imageUrl = URL.createObjectURL(file.raw);
  92. this.spliceContent(res.index, 1, {type: 'image', value: imageUrl, visible: false})
  93. },
  94. beforeImageUpload(file) {
  95. const isJPG = file.type === 'image/jpeg';
  96. const isLt2M = file.size / 1024 / 1024 < 2;
  97. console.info(file)
  98. if (!isJPG) {
  99. this.$message.error('上传头像图片只能是 JPG 格式!');
  100. }
  101. if (!isLt2M) {
  102. this.$message.error('上传头像图片大小不能超过 2MB!');
  103. }
  104. return isJPG && isLt2M;
  105. },
  106. handleMouseIn (index) {
  107. let item = this.contentList[index];
  108. item.visible = true;
  109. this.spliceContent(index, 1, item);
  110. },
  111. handleMouseOut (index) {
  112. let item = this.contentList[index];
  113. item.visible = false;
  114. this.spliceContent(index, 1, item);
  115. },
  116. finishEdit () {
  117. }
  118. },
  119. mounted () {
  120. this.contentList = this.contents.map(el => {
  121. el.visible = false;
  122. return el;
  123. });
  124. }
  125. }
  126. </script>
  127. <style scoped>
  128. .editor-viewer {
  129. width: 600px;
  130. height: 600px;
  131. border: 1px solid #ddd;
  132. position: relative;
  133. }
  134. .content-viewer {
  135. width: 100%;
  136. height: 552px;
  137. overflow-y: scroll;
  138. overflow-x: hidden;
  139. }
  140. .editor-btn-viewer {
  141. width: 100%;
  142. position: absolute;
  143. bottom: 0;
  144. left: 0;
  145. }
  146. .el-button {
  147. background-color: #eee;
  148. }
  149. .editor-btn{
  150. width: 50%;
  151. padding: 15px;
  152. outline: none;
  153. border: 1px solid #ddd;
  154. border-radius: 0;
  155. margin: 0;
  156. font-size: 16px;
  157. }
  158. .el-button:hover {
  159. color: #409eff;
  160. border-color: #c6e2ff;
  161. background-color: #ecf5ff;
  162. }
  163. .content-list {
  164. padding: 5px;
  165. }
  166. .editor-item +.editor-item{
  167. margin-top: 5px;
  168. }
  169. .editor-item {
  170. position: relative;
  171. }
  172. div.editor-item:hover{
  173. box-shadow: 0 0 10px #ccc;
  174. }
  175. .editor-item>.textarea,
  176. .editor-item>img{
  177. width: 100%;
  178. height: auto;
  179. border: 1px solid #ccc;
  180. min-height: 200px;
  181. text-align: left;
  182. }
  183. .editor-item>img{
  184. width: 571px;
  185. }
  186. .editor-item>textarea{
  187. resize: none;
  188. }
  189. .editor-item-ops {
  190. height: 50px;
  191. position: absolute;
  192. right: 6px;
  193. bottom: 0;
  194. z-index:100;
  195. }
  196. .editor-item-ops > .editor-btn {
  197. background-color: #666;
  198. }
  199. .add-module {
  200. border: 1px dashed #ccc;
  201. min-height: 100px;
  202. width: 100%;
  203. line-height: 100px;
  204. }
  205. </style>

  

转载于:https://www.cnblogs.com/yiyitong/p/9812502.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/775243
推荐阅读
相关标签
  

闽ICP备14008679号