Explorar o código

打印富文本

李帅 hai 3 meses
pai
achega
2efe9121ee

+ 1 - 0
package.json

@@ -57,6 +57,7 @@
57 57
     "js-beautify": "1.13.0",
58 58
     "js-cookie": "^3.0.1",
59 59
     "jsencrypt": "3.0.0-rc.1",
60
+    "kindeditor": "^4.1.10",
60 61
     "moment": "^2.30.1",
61 62
     "nprogress": "0.2.0",
62 63
     "path-to-regexp": "^7.0.0",

+ 366 - 0
src/components/editorr/index.vue

@@ -0,0 +1,366 @@
1
+<template>
2
+  <div class="kindeditor">
3
+    <textarea :id="id" name="content" v-model="outContent"></textarea>
4
+  </div>
5
+</template>
6
+ 
7
+<script>
8
+
9
+import '../../../node_modules/kindeditor/kindeditor-all.js'
10
+import '../../../node_modules/kindeditor/lang/zh-CN.js'
11
+import '../../../node_modules/kindeditor/themes/default/default.css'
12
+ 
13
+export default {
14
+  name: 'kindeditor',
15
+  data () {
16
+    return {
17
+      editor: null,
18
+      outContent: this.content
19
+    }
20
+  },
21
+  props: {
22
+    content: {
23
+      type: String,
24
+      default: ''
25
+    },
26
+    id: {
27
+      type: String,
28
+      required: true
29
+    },
30
+    width: {
31
+      type: String
32
+    },
33
+    height: {
34
+      type: String
35
+    },
36
+    minWidth: {
37
+      type: Number,
38
+      default: 650
39
+    },
40
+    minHeight: {
41
+      type: Number,
42
+      default: 100
43
+    },
44
+    items: {
45
+      type: Array,
46
+      default: function () {
47
+        return [
48
+          'undo', 'redo', '|', 'preview', 'print', 'cut', 'copy', 'paste',
49
+          'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
50
+          'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
51
+          'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
52
+          'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
53
+          'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat'
54
+        ]
55
+      }
56
+    },
57
+    noDisableItems: {
58
+      type: Array,
59
+      default: function () {
60
+        return ['source', 'fullscreen']
61
+      }
62
+    },
63
+    filterMode: {
64
+      type: Boolean,
65
+      default: true
66
+    },
67
+    htmlTags: {
68
+      type: Object,
69
+      default: function () {
70
+        return {
71
+          font: ['color', 'size', 'face', '.background-color'],
72
+          span: ['style'],
73
+          div: ['class', 'align', 'style'],
74
+          table: ['class', 'border', 'cellspacing', 'cellpadding', 'width', 'height', 'align', 'style'],
75
+          'td,th': ['class', 'align', 'valign', 'width', 'height', 'colspan', 'rowspan', 'bgcolor', 'style'],
76
+          a: ['class', 'href', 'target', 'name', 'style'],
77
+          embed: ['src', 'width', 'height', 'type', 'loop', 'autostart', 'quality',
78
+            'style', 'align', 'allowscriptaccess', '/'],
79
+          img: ['src', 'width', 'height', 'border', 'alt', 'title', 'align', 'style', '/'],
80
+          hr: ['class', '/'],
81
+          br: ['/'],
82
+          'p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6': ['align', 'style'],
83
+          'tbody,tr,strong,b,sub,sup,em,i,u,strike': []
84
+        }
85
+      }
86
+    },
87
+    wellFormatMode: {
88
+      type: Boolean,
89
+      default: true
90
+    },
91
+    resizeType: {
92
+      type: Number,
93
+      default: 2
94
+    },
95
+    themeType: {
96
+      type: String,
97
+      default: 'default'
98
+    },
99
+    langType: {
100
+      type: String,
101
+      default: 'zh-CN'
102
+    },
103
+    designMode: {
104
+      type: Boolean,
105
+      default: true
106
+    },
107
+    fullscreenMode: {
108
+      type: Boolean,
109
+      default: false
110
+    },
111
+    basePath: {
112
+      type: String
113
+    },
114
+    themesPath: {
115
+      type: String
116
+    },
117
+    pluginsPath: {
118
+      type: String,
119
+      default: ''
120
+    },
121
+    langPath: {
122
+      type: String
123
+    },
124
+    minChangeSize: {
125
+      type: Number,
126
+      default: 5
127
+    },
128
+    loadStyleMode: {
129
+      type: Boolean,
130
+      default: true
131
+    },
132
+    urlType: {
133
+      type: String,
134
+      default: ''
135
+    },
136
+    newlineTag: {
137
+      type: String,
138
+      default: 'p'
139
+    },
140
+    pasteType: {
141
+      type: Number,
142
+      default: 2
143
+    },
144
+    dialogAlignType: {
145
+      type: String,
146
+      default: 'page'
147
+    },
148
+    shadowMode: {
149
+      type: Boolean,
150
+      default: true
151
+    },
152
+    zIndex: {
153
+      type: Number,
154
+      default: 811213
155
+    },
156
+    useContextmenu: {
157
+      type: Boolean,
158
+      default: true
159
+    },
160
+    syncType: {
161
+      type: String,
162
+      default: 'form'
163
+    },
164
+    indentChar: {
165
+      type: String,
166
+      default: '\t'
167
+    },
168
+    cssPath: {
169
+      type: [ String, Array ]
170
+    },
171
+    cssData: {
172
+      type: String
173
+    },
174
+    bodyClass: {
175
+      type: String,
176
+      default: 'ke-content'
177
+    },
178
+    colorTable: {
179
+      type: Array
180
+    },
181
+    afterCreate: {
182
+      type: Function
183
+    },
184
+    afterChange: {
185
+      type: Function
186
+    },
187
+    afterTab: {
188
+      type: Function
189
+    },
190
+    afterFocus: {
191
+      type: Function
192
+    },
193
+    afterBlur: {
194
+      type: Function
195
+    },
196
+    afterUpload: {
197
+      type: Function
198
+    },
199
+    uploadJson: {
200
+      type: String
201
+    },
202
+    fileManagerJson: {
203
+      type: Function
204
+    },
205
+    allowPreviewEmoticons: {
206
+      type: Boolean,
207
+      default: true
208
+    },
209
+    allowImageUpload: {
210
+      type: Boolean,
211
+      default: true
212
+    },
213
+    allowFlashUpload: {
214
+      type: Boolean,
215
+      default: true
216
+    },
217
+    allowMediaUpload: {
218
+      type: Boolean,
219
+      default: true
220
+    },
221
+    allowFileUpload: {
222
+      type: Boolean,
223
+      default: true
224
+    },
225
+    allowFileManager: {
226
+      type: Boolean,
227
+      default: false
228
+    },
229
+    fontSizeTable: {
230
+      type: Array,
231
+      default: function () {
232
+        return ['9px', '10px', '12px', '14px', '16px', '18px', '24px', '32px']
233
+      }
234
+    },
235
+    imageTabIndex: {
236
+      type: Number,
237
+      default: 0
238
+    },
239
+    formatUploadUrl: {
240
+      type: Boolean,
241
+      default: true
242
+    },
243
+    fullscreenShortcut: {
244
+      type: Boolean,
245
+      default: false
246
+    },
247
+    extraFileUploadParams: {
248
+      type: Array,
249
+      default: function () {
250
+        return []
251
+      }
252
+    },
253
+    filePostName: {
254
+      type: String,
255
+      default: 'imgFile'
256
+    },
257
+    fillDescAfterUploadImage: {
258
+      type: Boolean,
259
+      default: false
260
+    },
261
+    afterSelectFile: {
262
+      type: Function
263
+    },
264
+    pagebreakHtml: {
265
+      type: String,
266
+      default: '<hr style=”page-break-after: always;” class=”ke-pagebreak” />'
267
+    },
268
+    allowImageRemote: {
269
+      type: Boolean,
270
+      default: true
271
+    },
272
+    autoHeightMode: {
273
+      type: Boolean,
274
+      default: false
275
+    },
276
+    fixToolBar: {
277
+      type: Boolean,
278
+      default: false
279
+    },
280
+    tabIndex: {
281
+      type: Number
282
+    }
283
+  },
284
+  watch: {
285
+    content (val) {
286
+      this.editor && val !== this.outContent && this.editor.html(val)
287
+    },
288
+    outContent (val) {
289
+      this.$emit('update:content', val)
290
+      this.$emit('on-content-change', val)
291
+    }
292
+  },
293
+  mounted () {
294
+    var _this = this
295
+    _this.editor = window.KindEditor.create('#' + this.id, {
296
+      width: _this.width,
297
+      height: _this.height,
298
+      minWidth: _this.minWidth,
299
+      minHeight: _this.minHeight,
300
+      items: _this.items,
301
+      noDisableItems: _this.noDisableItems,
302
+      filterMode: _this.filterMode,
303
+      htmlTags: _this.htmlTags,
304
+      wellFormatMode: _this.wellFormatMode,
305
+      resizeType: _this.resizeType,
306
+      themeType: _this.themeType,
307
+      langType: _this.langType,
308
+      designMode: _this.designMode,
309
+      fullscreenMode: _this.fullscreenMode,
310
+      basePath: _this.basePath,
311
+      themesPath: _this.cssPath,
312
+      pluginsPath: _this.pluginsPath,
313
+      langPath: _this.langPath,
314
+      minChangeSize: _this.minChangeSize,
315
+      loadStyleMode: _this.loadStyleMode,
316
+      urlType: _this.urlType,
317
+      newlineTag: _this.newlineTag,
318
+      pasteType: _this.pasteType,
319
+      dialogAlignType: _this.dialogAlignType,
320
+      shadowMode: _this.shadowMode,
321
+      zIndex: _this.zIndex,
322
+      useContextmenu: _this.useContextmenu,
323
+      syncType: _this.syncType,
324
+      indentChar: _this.indentChar,
325
+      cssPath: _this.cssPath,
326
+      cssData: _this.cssData,
327
+      bodyClass: _this.bodyClass,
328
+      colorTable: _this.colorTable,
329
+      afterCreate: _this.afterCreate,
330
+      afterChange: function () {
331
+        _this.afterChange
332
+        _this.outContent = this.html()
333
+      },
334
+      afterTab: _this.afterTab,
335
+      afterFocus: _this.afterFocus,
336
+      afterBlur: _this.afterBlur,
337
+      afterUpload: _this.afterUpload,
338
+      uploadJson: _this.uploadJson,
339
+      fileManagerJson: _this.fileManagerJson,
340
+      allowPreviewEmoticons: _this.allowPreviewEmoticons,
341
+      allowImageUpload: _this.allowImageUpload,
342
+      allowFlashUpload: _this.allowFlashUpload,
343
+      allowMediaUpload: _this.allowMediaUpload,
344
+      allowFileUpload: _this.allowFileUpload,
345
+      allowFileManager: _this.allowFileManager,
346
+      fontSizeTable: _this.fontSizeTable,
347
+      imageTabIndex: _this.imageTabIndex,
348
+      formatUploadUrl: _this.formatUploadUrl,
349
+      fullscreenShortcut: _this.fullscreenShortcut,
350
+      extraFileUploadParams: _this.extraFileUploadParams,
351
+      filePostName: _this.filePostName,
352
+      fillDescAfterUploadImage: _this.fillDescAfterUploadImage,
353
+      afterSelectFile: _this.afterSelectFile,
354
+      pagebreakHtml: _this.pagebreakHtml,
355
+      allowImageRemote: _this.allowImageRemote,
356
+      autoHeightMode: _this.autoHeightMode,
357
+      fixToolBar: _this.fixToolBar,
358
+      tabIndex: _this.tabIndex
359
+    })
360
+  }
361
+}
362
+</script>
363
+ 
364
+<style>
365
+   
366
+</style>

+ 19 - 3
src/views/patientCenter/medical/index.vue

@@ -254,13 +254,22 @@
254 254
             ></el-option>
255 255
           </el-select>
256 256
         </div>
257
-        <vue-editor
257
+        <!-- <vue-editor
258 258
           id="editor"
259 259
           :disabled="true"
260 260
           useCustomImageHandler
261 261
           v-model="protocolTemplateContent"
262 262
         >
263
-        </vue-editor>
263
+        </vue-editor> -->
264
+
265
+
266
+        <editor
267
+          id="editor_id"
268
+          height="500px"
269
+          :content.sync="protocolTemplateContent"
270
+          :loadStyleMode="false"
271
+          @on-content-change="onContentChange"
272
+        ></editor>
264 273
       </div>
265 274
       <span slot="footer" class="dialog-footer">
266 275
         <el-button @click="cancel">取 消</el-button>
@@ -279,6 +288,8 @@ import {
279 288
 import { VueEditor } from 'vue2-editor'
280 289
 
281 290
 import initName from '@/utils/initName.js'
291
+
292
+import editor from '@/components/editorr/index'
282 293
 export default {
283 294
   name: 'EitcErmPcIndex',
284 295
   mixins: [initName],
@@ -289,7 +300,8 @@ export default {
289 300
     }
290 301
   },
291 302
   components: {
292
-    VueEditor
303
+    VueEditor,
304
+    editor
293 305
   },
294 306
   data() {
295 307
     return {
@@ -318,6 +330,10 @@ export default {
318 330
       })
319 331
       this.list = res.data
320 332
     },
333
+    
334
+    onContentChange(val) {
335
+      this.protocolTemplateContent = val
336
+    },
321 337
     async initInformedConsentFormOption() {
322 338
       const res = await informedConsentForm()
323 339
       this.templateNameOptions = res.data

+ 20 - 3
src/views/patientCenter/printMedical.vue

@@ -68,14 +68,25 @@
68 68
         </span>
69 69
       </div>
70 70
 
71
-      <vue-editor
71
+      <!-- <vue-editor
72 72
       id="editor"
73 73
       :disabled="true"
74 74
       style="margin-top: 20px;"
75 75
       useCustomImageHandler
76 76
       v-model="protocolTemplateContent"
77 77
     >
78
-    </vue-editor>
78
+    </vue-editor> -->
79
+
80
+    <div style="margin-top: 20px;width: 100%;" v-html="protocolTemplateContent"> </div>
81
+
82
+    <!-- <editor
83
+    style="margin-top: 20px;width: 100%;"
84
+          id="editor_id"
85
+          height="500px"
86
+          :content.sync="protocolTemplateContent"
87
+          :loadStyleMode="false"
88
+          @on-content-change="onContentChange"
89
+        ></editor> -->
79 90
       
80 91
     </div>
81 92
       <span slot="footer" class="dialog-footer">
@@ -91,11 +102,14 @@ import { findMedicalInfo , html2Pdf } from '@/api/allApi.js'
91 102
 import initName from '@/utils/initName.js';
92 103
 import { VueEditor } from 'vue2-editor'
93 104
 
105
+import editor from '@/components/editorr/index'
106
+
94 107
 export default {
95 108
   name: 'EitcErmPcPrintMedical',
96 109
   mixins: [initName],
97 110
   components: {
98
-    VueEditor
111
+    VueEditor,
112
+    editor
99 113
   },
100 114
   props: {
101 115
     printDialogVisible: {
@@ -140,6 +154,9 @@ export default {
140 154
   },
141 155
 
142 156
   methods: {
157
+    onContentChange(val) {
158
+      this.protocolTemplateContent = val
159
+    },
143 160
     async initList() {
144 161
       const res = await findMedicalInfo({
145 162
         medicalRecordId:this.medicalRecordId,

+ 36 - 18
src/views/settingsPage/protocolTemplate/addProtocolTypeDialog.vue

@@ -4,7 +4,7 @@
4 4
     <el-dialog
5 5
       :title="addProtocolTypeTitle"
6 6
       :visible.sync="addProtocolTypeDialog"
7
-      width="1000px"
7
+      width="800px"
8 8
       :close-on-press-escape="false"
9 9
       :close-on-click-modal="false"
10 10
       @close="cancel"
@@ -40,14 +40,22 @@
40 40
       </el-form>
41 41
 
42 42
       <div style="max-height: 65vh; overflow: auto">
43
-        <vue-editor
43
+        <!-- <vue-editor
44 44
           id="editor"
45 45
           :style="editorStyle"
46 46
           useCustomImageHandler
47 47
           v-model="ruleForm.protocolTemplateContent"
48 48
           @image-added="handleImageAdded"
49 49
         >
50
-        </vue-editor>
50
+        </vue-editor> -->
51
+
52
+        <editor
53
+          id="editor_id"
54
+          height="500px"
55
+          :content.sync="ruleForm.protocolTemplateContent"
56
+          :loadStyleMode="false"
57
+          @on-content-change="onContentChange"
58
+        ></editor>
51 59
       </div>
52 60
       <span slot="footer" class="dialog-footer">
53 61
         <el-button @click="cancel">取 消</el-button>
@@ -60,12 +68,15 @@
60 68
 <script>
61 69
 import { VueEditor } from 'vue2-editor'
62 70
 import { protocolTemplate, protocolTemplateUpdate } from '@/api/allApi.js'
63
-import axios from 'axios';
71
+import axios from 'axios'
72
+
73
+import editor from '@/components/editorr/index'
64 74
 
65 75
 export default {
66 76
   name: 'AddProtocolTypeDialog',
67 77
   components: {
68
-    VueEditor
78
+    VueEditor,
79
+    editor
69 80
   },
70 81
   props: {
71 82
     listInId: {
@@ -107,6 +118,9 @@ export default {
107 118
   },
108 119
   data() {
109 120
     return {
121
+      editorText: '直接初始化值', // 双向同步的变量
122
+      editorTextCopy: '', // content-change 事件回掉改变的对象
123
+
110 124
       addProtocolTypeDialog: false,
111 125
       diagnosisTypeTemplateList: [],
112 126
       ruleForm: {
@@ -133,6 +147,9 @@ export default {
133 147
     cancel() {
134 148
       this.addProtocolTypeDialog = false
135 149
     },
150
+    onContentChange(val) {
151
+      this.ruleForm.protocolTemplateContent = val
152
+    },
136 153
     async submit() {
137 154
       if (this.addProtocolTypeTitle === '新建') {
138 155
         this.ruleForm.protocolType = this.listInId
@@ -159,30 +176,28 @@ export default {
159 176
       this.addProtocolTypeDialog = false
160 177
     },
161 178
     handleImageAdded(file, Editor, cursorLocation, resetUploader) {
162
-      var formData = new FormData();
163
-      formData.append("image", file);
179
+      var formData = new FormData()
180
+      formData.append('image', file)
164 181
 
165 182
       axios({
166
-        url: "https://fakeapi.yoursite.com/images",
167
-        method: "POST",
183
+        url: 'https://fakeapi.yoursite.com/images',
184
+        method: 'POST',
168 185
         data: formData
169 186
       })
170
-        .then(result => {
171
-          const url = result.data.url; // Get url from response
172
-          Editor.insertEmbed(cursorLocation, "image", url);
173
-          resetUploader();
187
+        .then((result) => {
188
+          const url = result.data.url // Get url from response
189
+          Editor.insertEmbed(cursorLocation, 'image', url)
190
+          resetUploader()
191
+        })
192
+        .catch((err) => {
193
+          console.log(err)
174 194
         })
175
-        .catch(err => {
176
-          console.log(err);
177
-        });
178 195
     }
179
-
180 196
   }
181 197
 }
182 198
 </script>
183 199
 
184 200
 <style lang="scss" scoped>
185
-
186 201
 .df_box {
187 202
   display: flex;
188 203
   justify-content: space-between;
@@ -204,4 +219,7 @@ export default {
204 219
   }
205 220
 }
206 221
 
222
+::v-deep .kindeditor {
223
+  width: 900px;
224
+}
207 225
 </style>