Преглед на файлове

修改通知公示,以及富文本

余思翰 преди 10 месеца
родител
ревизия
b487664079
променени са 2 файла, в които са добавени 248 реда и са изтрити 20 реда
  1. 188
    1
      oa-ui/src/components/Editor/index.vue
  2. 60
    19
      oa-ui/src/views/index.vue

+ 188
- 1
oa-ui/src/components/Editor/index.vue Целия файл

@@ -13,6 +13,32 @@
13 13
       v-if="this.type == 'url'"
14 14
     >
15 15
     </el-upload>
16
+    <el-upload
17
+      :action="uploadUrl"
18
+      :before-upload="handleBeforeUploadVideo"
19
+      :on-success="handleUploadSuccessVideo"
20
+      :on-error="handleUploadErrorVideo"
21
+      name="file"
22
+      :show-file-list="false"
23
+      :headers="headers"
24
+      style="display: none"
25
+      ref="uploadVideo"
26
+      v-if="this.type == 'url'"
27
+    >
28
+    </el-upload>
29
+    <el-upload
30
+      :action="uploadUrl"
31
+      :before-upload="handleBeforeUploadFile"
32
+      :on-success="handleUploadSuccessFile"
33
+      :on-error="handleUploadErrorFile"
34
+      name="file"
35
+      :show-file-list="false"
36
+      :headers="headers"
37
+      style="display: none"
38
+      ref="uploadFile"
39
+      v-if="this.type == 'url'"
40
+    >
41
+    </el-upload>
16 42
     <div class="editor" ref="editor" :style="styles"></div>
17 43
   </div>
18 44
 </template>
@@ -24,6 +50,34 @@ import "quill/dist/quill.snow.css";
24 50
 import "quill/dist/quill.bubble.css";
25 51
 import { getToken } from "@/utils/auth";
26 52
 
53
+// 源码中是import直接倒入,这里要用Quill.import引入
54
+const Link = Quill.import("formats/link");
55
+// 自定义a链接
56
+class FileBlot extends Link {
57
+   
58
+  // 继承Link Blot
59
+  static create (value) {
60
+   
61
+    let node = undefined;
62
+    if (value && !value.href) {
63
+   
64
+      // 适应原本的Link Blot
65
+      node = super.create(value)
66
+    } else {
67
+   
68
+      // 自定义Link Blot
69
+      node = super.create(value.href)
70
+      node.href = value.href
71
+      node.innerText = value.innerText
72
+      // node.setAttribute('download', value.innerText);  // 左键点击即下载
73
+    }
74
+    return node;
75
+  }
76
+}
77
+FileBlot.blotName = "link" // 这里不用改,如果需要也可以保留原来的,这里用个新的blot
78
+FileBlot.tagName = "A"
79
+Quill.register(FileBlot) // 注册link
80
+
27 81
 export default {
28 82
   name: "Editor",
29 83
   props: {
@@ -49,9 +103,18 @@ export default {
49 103
     },
50 104
     /* 上传文件大小限制(MB) */
51 105
     fileSize: {
106
+      type: Number,
107
+      default: 50,
108
+    },
109
+    /* 上传图片大小限制(MB) */
110
+    imageSize: {
52 111
       type: Number,
53 112
       default: 5,
54 113
     },
114
+    videoSize: {
115
+      type: Number,
116
+      default: 500,
117
+    },
55 118
     /* 类型(base64格式、url格式) */
56 119
     type: {
57 120
       type: String,
@@ -77,7 +140,7 @@ export default {
77 140
             ["blockquote", "code-block"],                    // 引用  代码块
78 141
             [{ list: "ordered" }, { list: "bullet" }],       // 有序、无序列表
79 142
             [{ indent: "-1" }, { indent: "+1" }],            // 缩进
80
-            [{ size: ["small", false, "large", "huge"] }],   // 字体大小
143
+            [{ size: ["20px","14px","16px", "large", "huge"] }],   // 字体大小
81 144
             [{ header: [1, 2, 3, 4, 5, 6, false] }],         // 标题
82 145
             [{ color: [] }, { background: [] }],             // 字体颜色、字体背景颜色
83 146
             [{ align: [] }],                                 // 对齐方式
@@ -123,8 +186,11 @@ export default {
123 186
   },
124 187
   methods: {
125 188
     init() {
189
+      debugger
126 190
       const editor = this.$refs.editor;
127 191
       this.Quill = new Quill(editor, this.options);
192
+      var Size = Quill.import("formats/size");
193
+      Size.whitelist = ["14px","16px", "large","20px", "huge"];
128 194
       // 如果设置了上传地址则自定义图片上传事件
129 195
       if (this.type == 'url') {
130 196
         let toolbar = this.Quill.getModule("toolbar");
@@ -135,6 +201,20 @@ export default {
135 201
             this.quill.format("image", false);
136 202
           }
137 203
         });
204
+        toolbar.addHandler("video", (value) => {
205
+          if (value) {
206
+            this.$refs.uploadVideo.$children[0].$refs.input.click();
207
+          } else {
208
+            this.quill.format("video", false);
209
+          }
210
+        });
211
+        toolbar.addHandler("link", (value) => {
212
+          if (value) {
213
+            this.$refs.uploadFile.$children[0].$refs.input.click();
214
+          } else {
215
+            this.quill.format("link", false);
216
+          }
217
+        });
138 218
       }
139 219
       this.Quill.pasteHTML(this.currentValue);
140 220
       this.Quill.on("text-change", (delta, oldDelta, source) => {
@@ -164,6 +244,36 @@ export default {
164 244
         this.$message.error(`图片格式错误!`);
165 245
         return false;
166 246
       }
247
+      // 校检文件大小
248
+      if (this.imageSize) {
249
+        const isLt = file.size / 1024 / 1024 < this.imageSize;
250
+        if (!isLt) {
251
+          this.$message.error(`上传文件大小不能超过 ${this.imageSize} MB!`);
252
+          return false;
253
+        }
254
+      }
255
+      return true;
256
+    },
257
+    handleBeforeUploadVideo(file) {
258
+      const type = ["video/mp4"];
259
+      const isVideo = type.includes(file.type);
260
+      // 检验文件格式
261
+      if (!isVideo) {
262
+        this.$message.error(`视频格式错误!`);
263
+        return false;
264
+      }
265
+      // 校检文件大小
266
+      if (this.videoSize) {
267
+        const isLt = file.size / 1024 / 1024 < this.videoSize;
268
+        if (!isLt) {
269
+          this.$message.error(`上传文件大小不能超过 ${this.videoSize} MB!`);
270
+          return false;
271
+        }
272
+      }
273
+      return true;
274
+    },
275
+    // 上传前校检格式和大小
276
+    handleBeforeUploadFile(file) {
167 277
       // 校检文件大小
168 278
       if (this.fileSize) {
169 279
         const isLt = file.size / 1024 / 1024 < this.fileSize;
@@ -175,6 +285,7 @@ export default {
175 285
       return true;
176 286
     },
177 287
     handleUploadSuccess(res, file) {
288
+      debugger
178 289
       // 如果上传成功
179 290
       if (res.code == 200) {
180 291
         // 获取富文本组件实例
@@ -189,9 +300,50 @@ export default {
189 300
         this.$message.error("图片插入失败");
190 301
       }
191 302
     },
303
+    handleUploadSuccessVideo(res, file) {
304
+      // 如果上传成功
305
+      if (res.code == 200) {
306
+        // 获取富文本组件实例
307
+        let quill = this.Quill;
308
+        // 获取光标所在位置
309
+        let length = quill.getSelection().index;
310
+        // 插入图片  res.url为服务器返回的图片地址
311
+        quill.insertEmbed(length, "video", process.env.VUE_APP_BASE_API + res.fileName);
312
+        // 调整光标到最后
313
+        quill.setSelection(length + 1);
314
+      } else {
315
+        this.$message.error("视频插入失败");
316
+      }
317
+    },
318
+    handleUploadSuccessFile(res, file) {
319
+      // 如果上传成功
320
+      if (res.code == 200) {
321
+        // 获取富文本组件实例
322
+        let quill = this.Quill;
323
+        // 获取光标所在位置
324
+        let length = quill.getSelection().index;
325
+        // 插入文件  res.url为服务器返回的图片地址
326
+        quill.insertEmbed(length, "link", 
327
+          {
328
+            href: process.env.VUE_APP_BASE_API + res.fileName, 
329
+            innerText: res.originalFilename
330
+          },
331
+        );
332
+        // 调整光标到最后
333
+        quill.setSelection(length + 1);
334
+      } else {
335
+        this.$message.error("文件插入失败");
336
+      }
337
+    },
192 338
     handleUploadError() {
193 339
       this.$message.error("图片插入失败");
194 340
     },
341
+    handleUploadErrorVideo() {
342
+      this.$message.error("视频插入失败");
343
+    },
344
+    handleUploadErrorFile() {
345
+      this.$message.error("文件插入失败");
346
+    },
195 347
   },
196 348
 };
197 349
 </script>
@@ -204,6 +356,12 @@ export default {
204 356
 .quill-img {
205 357
   display: none;
206 358
 }
359
+.ql-align-right{
360
+  text-align: right;
361
+}
362
+.ql-align-center{
363
+  text-align: center;
364
+}
207 365
 .ql-snow .ql-tooltip[data-mode="link"]::before {
208 366
   content: "请输入链接地址:";
209 367
 }
@@ -223,14 +381,38 @@ export default {
223 381
 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
224 382
   content: "10px";
225 383
 }
384
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
385
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
386
+  content: "14px";
387
+}
388
+.ql-size-14px {
389
+  font-size: 14px;
390
+}
391
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
392
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
393
+  content: "16px";
394
+}
395
+.ql-size-16px {
396
+  font-size: 16px;
397
+}
398
+
226 399
 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
227 400
 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
228 401
   content: "18px";
229 402
 }
403
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
404
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
405
+  content: "20px";
406
+}
407
+.ql-size-20px {
408
+  font-size: 20px;
409
+}
230 410
 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
231 411
 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
232 412
   content: "32px";
233 413
 }
414
+
415
+
234 416
 .ql-snow .ql-picker.ql-header .ql-picker-label::before,
235 417
 .ql-snow .ql-picker.ql-header .ql-picker-item::before {
236 418
   content: "文本";
@@ -271,4 +453,9 @@ export default {
271 453
 .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
272 454
   content: "等宽字体";
273 455
 }
456
+.ql-video {
457
+  width: 100%;
458
+  height: 425px;
459
+}
274 460
 </style>
461
+

+ 60
- 19
oa-ui/src/views/index.vue Целия файл

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2024-01-03 09:23:11
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2024-07-16 09:50:08
5
+ * @LastEditTime: 2024-07-16 15:17:54
6 6
 -->
7 7
 
8 8
 <template>
@@ -59,9 +59,9 @@
59 59
         </div>
60 60
       </el-col>
61 61
       <el-col :span="16" :xs="24">
62
-        <div class="header">公告</div>
62
+        <div class="header">通知公示</div>
63 63
         <div class="notice-content">
64
-          <el-table v-loading="noticeLoading" :data="noticeList" height="320px" @row-click="handleRowClick">
64
+          <el-table v-loading="noticeLoading" :data="noticeList" height="320px">
65 65
             <!-- <el-table-column label="序号" align="center" prop="noticeId" width="100" /> -->
66 66
             <el-table-column label="公告类型" align="center" prop="noticeType" width="100">
67 67
               <template slot-scope="scope">
@@ -75,6 +75,12 @@
75 75
                 <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
76 76
               </template>
77 77
             </el-table-column>
78
+            <el-table-column label="操作" width="90" align="center">
79
+              <template slot-scope="scope">
80
+                <el-button size="mini" type="text" icon="el-icon-view"
81
+                  @click="handleRowClick(scope.row)">查看详情</el-button>
82
+              </template>
83
+            </el-table-column>
78 84
           </el-table>
79 85
           <div style="text-align: right;margin-top: 20px;">
80 86
             <el-pagination @current-change="getNotice" :current-page.sync="noticeQueryParams.pageNum"
@@ -92,9 +98,9 @@
92 98
       </el-col> -->
93 99
     </el-row>
94 100
 
95
-    <el-dialog title="" :visible.sync="noticeOpen" width="65%" append-to-body>
101
+    <el-dialog title="" :visible.sync="noticeOpen" width="750px" append-to-body>
96 102
       <h2 class="text-center">{{ clickNotice.noticeTitle }}</h2>
97
-      <div v-html="clickNotice.noticeContent"></div>
103
+      <div class="pre-formatted" v-html="clickNotice.noticeContent"></div>
98 104
     </el-dialog>
99 105
   </div>
100 106
 </template>
@@ -123,7 +129,7 @@ export default {
123 129
   },
124 130
   data() {
125 131
     return {
126
-      noticeOpen:false,
132
+      noticeOpen: false,
127 133
       times: new Date(),
128 134
       user: {
129 135
         dept: {}
@@ -133,7 +139,7 @@ export default {
133 139
       projectData: [],
134 140
       noticeList: [],// 公告表格数据
135 141
       noticeTotal: 0,
136
-      clickNotice:{},
142
+      clickNotice: {},
137 143
       noticeLoading: true,
138 144
       noticeQueryParams: {
139 145
         pageNum: 1,
@@ -156,7 +162,7 @@ export default {
156 162
           bgColor: '#785aee',
157 163
           boxShadow: '0 5px 20px rgba(120,90,238,0.5)',
158 164
           path: '/task/process',
159
-          privilege:['system:deployment:add']
165
+          privilege: ['system:deployment:add']
160 166
         }, {
161 167
           id: 2,
162 168
           name: '待办任务',
@@ -164,7 +170,7 @@ export default {
164 170
           bgColor: '#e66794',
165 171
           boxShadow: '0 5px 20px rgba(230,103,148,0.5)',
166 172
           path: '/task/todo',
167
-          privilege:['system:deployment:add']
173
+          privilege: ['system:deployment:add']
168 174
         }, {
169 175
           id: 3,
170 176
           name: '已办任务',
@@ -172,7 +178,7 @@ export default {
172 178
           bgColor: '#6389f4',
173 179
           boxShadow: '0 5px 20px rgba(99,137,244,0.5)',
174 180
           path: '/task/finished',
175
-          privilege:['system:deployment:add']
181
+          privilege: ['system:deployment:add']
176 182
         }, {
177 183
           id: 4,
178 184
           name: '项目台账',
@@ -180,7 +186,7 @@ export default {
180 186
           bgColor: '#e64c56',
181 187
           boxShadow: '0 5px 20px rgba(230,76,86,0.5)',
182 188
           path: '/product/account/project',
183
-          privilege:['oa:project:query']
189
+          privilege: ['oa:project:query']
184 190
         }, {
185 191
           id: 5,
186 192
           name: '车辆管理',
@@ -188,7 +194,7 @@ export default {
188 194
           bgColor: '#eeb62f',
189 195
           boxShadow: '0 5px 20px rgba(238,182,47,0.5)',
190 196
           path: '/oa/car/index',
191
-          privilege:['oa:car:list']
197
+          privilege: ['oa:car:list']
192 198
         }, {
193 199
           id: 6,
194 200
           name: '设备管理',
@@ -196,7 +202,7 @@ export default {
196 202
           bgColor: '#0be1bd',
197 203
           boxShadow: '0 5px 20px rgba(11,225,189,0.5)',
198 204
           path: '/oa/device/equipment',
199
-          privilege:['oa:device:list']
205
+          privilege: ['oa:device:list']
200 206
         }, {
201 207
           id: 7,
202 208
           name: '投标管理',
@@ -204,7 +210,7 @@ export default {
204 210
           bgColor: '#F7C59F',
205 211
           boxShadow: '0 5px 20px rgba(247,197,159,0.5)',
206 212
           path: '/business/tender',
207
-          privilege:['oa:tender:query']
213
+          privilege: ['oa:tender:query']
208 214
         }, {
209 215
           id: 8,
210 216
           name: '人事管理',
@@ -212,8 +218,8 @@ export default {
212 218
           bgColor: '#20B2AA',
213 219
           boxShadow: '0 5px 20px rgba(32,178,170,0.5)',
214 220
           path: '/oa/staff/people',
215
-          privilege:['oa:salary:list']
216
-        }, 
221
+          privilege: ['oa:salary:list']
222
+        },
217 223
         // {
218 224
         //   id: 9,
219 225
         //   name: '预算管理',
@@ -300,15 +306,33 @@ export default {
300 306
         return null
301 307
       }
302 308
     },
303
-    handleRowClick(row){
304
-      console.log(row);
309
+    handleRowClick(row) {
305 310
       this.clickNotice = row;
311
+      this.clickNotice.noticeContent = this.format(row.noticeContent);
306 312
       this.noticeOpen = true;
313
+    },
314
+    format(html) {
315
+      var GRT = [
316
+        // img 样式
317
+        ['img', "max-width:100%;height:auto;"],
318
+      ];
319
+      for (let i = 0; i < GRT.length; i++) {
320
+        html = html.replace(new RegExp('<' + GRT[i][0] + '>|<' + GRT[i][0] + ' (.*?)>', 'gi'), function (word) {
321
+          // 分析 dom 上是否带有 style=""
322
+          if (word.indexOf('style=') != -1) {
323
+            var regIn = new RegExp('<' + GRT[i][0] + '(.*?)style="(.*?)"(.*?)(/?)>', 'gi');
324
+            return word.replace(regIn, '<' + GRT[i][0] + '$1style="$2 ' + GRT[i][1] + '"$3$4>');
325
+          } else {
326
+            var regIn = new RegExp('<' + GRT[i][0] + '(.*?)(/?)>', 'gi');
327
+            return word.replace(regIn, '<' + GRT[i][0] + '$1 style="' + GRT[i][1] + '$2">');
328
+          }
329
+        });
330
+      }
331
+      return html;
307 332
     }
308 333
   }
309 334
 }
310 335
 </script>
311
-
312 336
 <style scoped lang="scss">
313 337
 .home {
314 338
   padding: 20px 40px;
@@ -419,6 +443,23 @@ export default {
419 443
   border-radius: 15px;
420 444
 }
421 445
 
446
+.pre-formatted {
447
+  white-space: pre-wrap;
448
+  /* css-2.1, curent FF, Opera, Safari */
449
+  word-wrap: break-word;
450
+
451
+  /* Internet Explorer 5.5+ */
452
+  p {
453
+    width: 100% !important;
454
+    height: 100% !important;
455
+
456
+    img {
457
+      width: 100%;
458
+      height: 100%;
459
+    }
460
+  }
461
+}
462
+
422 463
 ::v-deep .el-calendar-table .el-calendar-day {
423 464
   height: 39px;
424 465
   text-align: center;

Loading…
Отказ
Запис