leditor.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <template>
  2. <view class="editor">
  3. <view class="cons">
  4. <view v-if="read">
  5. <u-parse :content="value"></u-parse>
  6. </view>
  7. <view v-else>
  8. <view class="toolbar" @tap="format">
  9. <view :class="formats.bold ? 'ql-active' : ''" class="icon" data-name="bold" title="加粗">&#xec84;</view>
  10. <view :class="formats.align === 'left' ? 'ql-active' : ''" class="icon" data-name="align" data-value="left" title="左对齐">&#xec86;</view>
  11. <view :class="formats.align === 'center' ? 'ql-active' : ''" class="icon" data-name="align" data-value="center" title="居中对齐">&#xec80;</view>
  12. <view :class="formats.align === 'right' ? 'ql-active' : ''" class="icon" data-name="align" data-value="right" title="右对齐">&#xec82;</view>
  13. <view :class="formats.align === 'justify' ? 'ql-active' : ''" class="icon" data-name="align" data-value="justify" title="两端对齐">&#xec87;</view>
  14. <view :class="formats.lineHeight ? 'ql-active' : ''" class="icon" data-name="lineHeight" data-value="2" title="行距">&#xe7f8;</view>
  15. <view :class="formats.list === 'ordered' ? 'ql-active' : ''" class="icon" data-name="list" data-value="ordered" title="编号">&#xe7f5;</view>
  16. <!-- <view class="icon" title="分割线" @tap="insertDivider">&#xe620;</view> -->
  17. <!-- <view class="icon" @tap="insertDate">&#xe8b8;</view> -->
  18. <view class="icon" @tap="insertImage" title="插入图片">&#xe64a;</view>
  19. <view class="icon" @tap="clear" title="清空内容">&#xe8b6;</view>
  20. </view>
  21. <editor id="editor" class="ql-container" :placeholder="placeholder" showImgSize showImgToolbar showImgResize @input="editorChange" @statuschange="onStatusChange" :read-only="false" @ready="onEditorReady"></editor>
  22. </view>
  23. </view>
  24. </view>
  25. </template>
  26. <script>
  27. export default {
  28. name: 'leditor',
  29. props: {
  30. value: {
  31. default: ''
  32. },
  33. read: {
  34. type: Boolean,
  35. default: false
  36. },
  37. placeholder: {
  38. type: String,
  39. default: '输入内容'
  40. }
  41. },
  42. data() {
  43. return {
  44. ip: this.http.ip,
  45. ready: false,
  46. formats: {}
  47. };
  48. },
  49. methods: {
  50. //初始化
  51. onEditorReady() {
  52. uni.createSelectorQuery()
  53. .in(this)
  54. .select('#editor')
  55. .context((res) => {
  56. this.editorCtx = res.context;
  57. })
  58. .exec();
  59. },
  60. //设置编辑器内容
  61. setContents() {
  62. if (!this.read) {
  63. setTimeout(() => {
  64. this.editorCtx.setContents({
  65. html: this.value
  66. });
  67. }, 3000);
  68. }
  69. },
  70. //修改样式
  71. format(e) {
  72. let { name, value } = e.target.dataset;
  73. if (!name) return;
  74. this.editorCtx.format(name, value);
  75. },
  76. //插入分割线
  77. insertDivider() {
  78. this.editorCtx.insertDivider();
  79. },
  80. //插入日期
  81. insertDate() {
  82. const date = new Date();
  83. const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
  84. this.editorCtx.insertText({
  85. text: formatDate
  86. });
  87. },
  88. //改变编辑器内样式
  89. onStatusChange(e) {
  90. const formats = e.detail;
  91. this.formats = formats;
  92. },
  93. //清除全部内容
  94. clear() {
  95. this.editorCtx.clear();
  96. },
  97. //内容改变时
  98. editorChange: function (e) {
  99. this.$emit('input', e.detail.html);
  100. },
  101. //插入图片
  102. insertImage() {
  103. uni.chooseImage({
  104. count: 9, //默认9
  105. sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
  106. sourceType: ['album'], //从相册选择
  107. success: (chooseImageRes) => {
  108. chooseImageRes.tempFilePaths.forEach((item) => {
  109. uni.showLoading({ title: '正在上传图片...', mask: true });
  110. uni.uploadFile({
  111. url: this.ip + '/common/upload',
  112. filePath: item,
  113. name: 'file',
  114. header: { Authorization: this.getUser().token },
  115. success: (res) => {
  116. uni.hideLoading();
  117. let result = JSON.parse(res.data);
  118. if (result.code === 200) {
  119. this.editorCtx.insertImage({
  120. src: this.ip + result.fileName,
  121. alt: '图像'
  122. });
  123. } else {
  124. uni.showModal({ content: result.msg, showCancel: false });
  125. }
  126. }
  127. });
  128. });
  129. }
  130. });
  131. }
  132. }
  133. };
  134. </script>
  135. <style lang="scss">
  136. .editor {
  137. padding: 0px 0px 0px 0px;
  138. .cons {
  139. width: 100%;
  140. .toolbar {
  141. border-bottom: 0px;
  142. background-color: whitesmoke;
  143. border-radius: 0px 0px 0px 0px;
  144. .icon {
  145. display: inline-block;
  146. cursor: pointer;
  147. font-size: 20px;
  148. padding: 6px 6px;
  149. width: 23px;
  150. height: 23px;
  151. }
  152. .ql-active {
  153. color: #06c;
  154. }
  155. }
  156. .ql-container {
  157. padding: 10px;
  158. height: 320px;
  159. font-size: 15px;
  160. background-color: white;
  161. border-bottom: 1px solid #eeeeee;
  162. image {
  163. width: 100%;
  164. }
  165. }
  166. }
  167. }
  168. </style>