long
2021-09-17 0b1092dde2314d223d90ec27b095b41690eab1bb
提交 | 用户 | age
36b711 1 <template>
L 2   <div class="app-container">
7f89d0 3     <!-- 返回按钮和标题 -->
C 4     <!-- <el-page-header class="mb20" content="xx" @back="$router.go(-1)" /> -->
5
36b711 6     <!-- 搜索区 ↓↓↓↓↓↓↓↓↓↓ -->
L 7     <el-form v-show="showSearch" ref="searchForm" :inline="true">
8       <el-form-item label="角色名称">
9         <el-input
10           v-model="keyWord"
11           placeholder="请输入角色名称"
12           clearable
13           size="small"
14           style="width: 240px"
15           maxlength="50"
16           @keyup.enter.native="reGetList"
17         />
18       </el-form-item>
19       <el-form-item>
20         <el-button type="cyan" icon="el-icon-search" size="mini" @click="reGetList">搜索</el-button>
21         <el-button icon="el-icon-refresh" size="mini" @click="resetHandle">重置</el-button>
22       </el-form-item>
23     </el-form>
24     <!-- 搜索区 ↑↑↑↑↑↑↑↑↑↑ -->
25
26     <!-- 操作区 ↓↓↓↓↓↓↓↓↓↓ -->
27     <el-row :gutter="10" class="mb8">
7f89d0 28       <!-- 权限判断 v-if="getAuthValueFN('xxx_add')" -->
36b711 29       <el-col :span="1.5">
L 30         <el-button
31           type="primary"
32           icon="el-icon-plus"
33           size="mini"
34           @click="showAddDialog"
35         >新增</el-button>
36       </el-col>
eaaa5b 37       <el-col :span="1.5">
L 38         <el-button
39           v-if="getAuthValueFN('xxxx')"
40           type="primary"
41           icon="el-icon-download"
42           size="mini"
43           @click="exportList"
f84ee2 44         >导出列表</el-button>
eaaa5b 45       </el-col>
L 46       <el-col :span="1.5">
47         <el-button
48           v-if="getAuthValueFN('xxxx')"
49           type="primary"
50           class="rel"
51           size="mini"
52           icon="el-icon-upload2"
53           style="overflow:hidden"
3dcc7c 54         >导入数据
eaaa5b 55           <input id="upload" ref="upload" type="file" @change="fileChange">
L 56         </el-button>
57       </el-col>
f84ee2 58       <el-col :span="1.5">
L 59         <!-- 导出模版 -->
60         <a v-if="getAuthValueFN('xxxx')" href="./static/excel/schedule.xls" download>
5f052d 61           <el-button type="primary" icon="el-icon-download" size="mini">下载导入模版</el-button>
f84ee2 62         </a>
L 63       </el-col>
64
36b711 65       <right-toolbar :show-search.sync="showSearch" @queryTable="getList" />
L 66     </el-row>
67     <!-- 操作区 ↑↑↑↑↑↑↑↑↑↑ -->
68
54e0b4 69     <el-table :data="list" :max-height="clienHeight" stripe>
36b711 70       <el-table-column type="index" label="序号" align="center" width="60" />
1dcdda 71       <el-table-column label="头像" prop="headImg" align="center" min-width="100">
L 72         <template slot-scope="scope">
73           <el-image :src="scope.row.headImg" style="width:50px;height:50px;" fit="contain" :preview-src-list="[scope.row.headImg]">
74             <div slot="error" class="image-slot">
75               <svg-icon icon-class="avatar" style="width:50px;height:50px;" />
76             </div>
77           </el-image>
78         </template>
79       </el-table-column>
36b711 80       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
L 81       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
1dcdda 82       <el-table-column label="专家建议" prop="adviceInfo" align="center" min-width="160">
L 83         <template slot-scope="scope">
84           <el-popover
85             placement="top-start"
86             width="400"
87             popper-class="el-popover_tableFilter"
88             trigger="hover"
89             :popper-options="{ removeOnDestroy: true }"
90           >
91             <div style="max-height: 500px;overflow-y: auto;">{{ scope.row.adviceInfo }}</div>
92             <div slot="reference" class="line-clamp-2" style="line-height: 1.2">{{ scope.row.adviceInfo }}</div>
93           </el-popover>
94         </template>
95       </el-table-column>
36b711 96       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
L 97       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
98       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
99       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
100       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
101       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
102       <el-table-column label="角色名称" prop="name" align="center" min-width="120" />
103       <el-table-column label="是否上架" prop="isUp" align="center" min-width="100">
104         <template slot-scope="scope">
7f89d0 105           <!-- 权限判断 v-if="getAuthValueFN('xxx_edit')" -->
36b711 106           <el-switch
L 107             v-model="scope.row.isUp"
108             :active-value="1"
109             :inactive-value="0"
110             @change="handleUpChange(scope.row)"
111           />
112         </template>
113       </el-table-column>
114       <el-table-column label="创建时间" prop="createTime" align="center" min-width="160" />
115       <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120" fixed="right">
116         <template slot-scope="scope">
7f89d0 117           <!-- 权限判断 v-if="getAuthValueFN('xxx_edit')" -->
36b711 118           <el-button
L 119             size="mini"
120             type="text"
121             icon="el-icon-edit"
122             @click="showEditDialog(scope.row)"
123           >编辑</el-button>
7f89d0 124           <!-- 权限判断 v-if="getAuthValueFN('xxx_del')" -->
36b711 125           <el-button
L 126             size="mini"
127             type="text warn"
128             icon="el-icon-delete"
129             @click="handleDelete(scope.row)"
130           >删除</el-button>
131         </template>
132       </el-table-column>
133     </el-table>
134
135     <!-- 新增&编辑 -->
7f89d0 136     <el-dialog v-el-drag-dialog :title="(dialogData.type=='add'?'新增':'编辑') + objectName" width="500px" :visible.sync="dialogVisible" append-to-body :before-close="hideDialog" :close-on-click-modal="false">
36b711 137       <el-form ref="refDialog" :model="dialogData" label-width="110px" :rules="rules" size="small">
L 138         <el-form-item label="名称" prop="name">
139           <el-input v-model="dialogData.name" placeholder="请输入名称" maxlength="50" />
140         </el-form-item>
141         <el-form-item label="是否上架" prop="isUp">
142           <el-switch
143             v-model="dialogData.isUp"
144             :active-value="1"
145             :inactive-value="0"
146           />
147         </el-form-item>
eaaa5b 148         <el-form-item prop="uploadImgs">
L 149           <span slot="label">
150             图片<br><span style="color: #999;font-size: 12px">(xxx*xxx像素)</span>
151           </span>
152           <!-- 上传图片组件(单图) -->
153           <UploadSingleImg
154             ref="refUploadImg"
155             v-model="dialogData.uploadImgs"
156             @change.capture="$refs.refDialog.clearValidate()"
157           />
158         </el-form-item>
36b711 159       </el-form>
L 160       <div slot="footer" class="dialog-footer">
161         <el-button @click="hideDialog">取消</el-button>
162         <el-button type="primary" @click="submitHandle">确定</el-button>
163       </div>
164     </el-dialog>
165
166     <pagination
167       v-show="total>0"
168       :total="total"
169       :page.sync="pageNum"
170       :limit.sync="pageSize"
171       @pagination="getList"
172     />
eaaa5b 173
L 174     <!-- upload放大图片 -->
175     <el-dialog :visible.sync="uploadPreviewVisible" style="text-align:center">
176       <img style="max-width:100%" :src="uploadPreviewUrl" alt="">
177     </el-dialog>
178
36b711 179   </div>
L 180 </template>
181
182 <script>
183
eaaa5b 184 import UploadSingleImg from '@/components_simple/UploadSingleImg'
L 185 import mixin_upload from '@/mixins/upload.js' // 通用上传图片预览
36b711 186 export default {
L 187   name: 'Demo',
eaaa5b 188   components: { UploadSingleImg },
L 189   mixins: [mixin_upload],
36b711 190   data() {
L 191     return {
c00018 192       clienHeight: document.body.clientHeight - 240, // 列表最大高度(适用于列表列太多,不方便水平滑动时,需添加max-height)
36b711 193       showSearch: true, // 是否显示搜索区
7f89d0 194       keyWord: '', // 搜索区字段,可自行扩展其余字段
36b711 195
7f89d0 196       // TODO
C 197       objectName: 'xx', // 对象名称,用于删除提示、启用提示、弹窗标题等
198
199       // 数据列表
36b711 200       list: [],
L 201
202       // 弹窗数据
203       dialogVisible: false,
204       dialogData: {},
7f89d0 205
C 206       // 富文本编辑器
207       // rangenum: null,
36b711 208
L 209       // 分页 ↓↓↓↓↓↓↓↓↓↓
210       total: 0,
211       pageNum: 1,
212       pageSize: 20,
213       // 分页 ↑↑↑↑↑↑↑↑↑↑
214
215       // 表单校验
216       rules: {
217         name: [
218           { required: true, message: '名称不能为空', trigger: 'change' }
219         ],
220         isUp: [
221           { required: true, message: '是否上架不能为空', trigger: 'change' }
eaaa5b 222         ],
L 223         uploadImgs: [
224           { required: true, message: '图片不能为空' }
36b711 225         ]
L 226       }
227     }
228   },
229   mounted() {
230     this.init()
231   },
232   methods: {
233     // 初始化
234     init() {
235       this.getList()
236     },
237
7f89d0 238     // ========== 富文本相关
C 239     // 富文本编辑器的内容赋值
240     // catchData(content) {
241     //   if (content === '<p><br></p>') content = ''
242     //   try {
243     //     const currentRange = window.getSelection().getRangeAt(0)
244     //     this.rangenum = currentRange
245     //   } catch (e) {
246     //
247     //   }
248     //   this.$set(this.dialogData, 'content', content)
249     //   this.$refs[this.formName].validateField('content')
250     // },
251     // ========== 富文本相关
252
36b711 253     // 获取列表
L 254     getList() {
255       var { pageNum, pageSize, keyWord } = this
256       this.postFN({
7f89d0 257         // TODO url
36b711 258         url: 'xxx',
L 259         params: {
260           pageNum: pageNum,
261           pageSize: pageSize,
262           keyWord: keyWord
263         },
264         mockData: {
265           code: 100,
266           msg: '',
267           data: {
268             list: [{
269               id: 'xxx',
270               index: 1,
271               name: '超级管理员',
1dcdda 272               createTime: '2020-08-09 10:10:10',
L 273               adviceInfo: '啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦'
36b711 274             }],
L 275             total: 100
276           }
277         }
278       }, (inf) => {
7f89d0 279         // 测试用
36b711 280         for (var i = 0; i < 19; i++) {
L 281           inf.list.push({
282             id: 'xxx',
283             index: 1,
284             name: '超级管理员',
285             createTime: '2020-08-09 10:10:10'
286           })
287         }
288         this.list = inf.list || []
289         this.total = inf.total
290       })
291     },
292     // 重新获取列表
293     reGetList() {
294       this.pageNum = 1
295       this.getList()
296     },
297     // 重置
298     resetHandle() {
299       this.keyWord = ''
300       this.reGetList()
301     },
302     // 删除
303     handleDelete(item) {
304       // 打开二次确认弹窗
305       this.$confirm('是否确认删除该角色?', '提示', {
306         confirmButtonText: '确定',
307         cancelButtonText: '取消',
308         type: 'warning'
309       }).then(() => {
310         // 确定回调
7f89d0 311         // TODO url
36b711 312         this.postFN({
L 313           url: 'xxx',
314           params: {
315             id: item.id
316           },
317           mockData: {
318             code: 100,
319             msg: '',
320             data: {}
321           }
322         }, () => {
323           this.getList()
324           this.$messageSuc('删除成功')
325         })
326       }).catch(() => {})
327     },
328     // 修改是否上架 todo
329     handleUpChange(item) {
330       const text = item.isUp === 1 ? '上架' : '下架'
331       this.$confirm('确认要' + text + '该角色吗?', '提示', {
332         confirmButtonText: '确定',
333         cancelButtonText: '取消',
334         type: 'warning'
335       }).then(() => {
336         this.postFN({
337           url: 'xxx',
7f89d0 338           // TODO url
36b711 339           params: {
L 340             id: item.id
341           },
342           mockData: {
343             code: 100,
344             msg: '',
345             data: {}
346           }
347         }, () => {
348           this.$messageSuc(text + '成功')
4dde14 349         }, (res) => {
L 350           item.isUp = item.isUp === 1 ? 0 : 1
351           this.$messageError(res.msg)
36b711 352         })
L 353       }).catch(() => {
354         item.isUp = item.isUp === 1 ? 0 : 1
355       })
356     },
357
358     // 打开新增弹窗
359     showAddDialog() {
360       var dialogData = {
361         type: 'add',
362         isUp: 1
363       }
364       this.dialogVisible = true
365       this.$nextTick(() => {
366         this.dialogData = dialogData
367         this.$refs['refDialog'].resetFields()
368       })
369     },
370     // 打开编辑弹框
371     showEditDialog(item) {
372       var dialogData = {
373         type: 'edit',
374         ...item
375       }
eaaa5b 376       dialogData.uploadImgs = [{ url: item.imgUrl, status: 'success' }]
L 377
36b711 378       console.log('dialogData', dialogData)
L 379       this.dialogVisible = true
380       this.$nextTick(() => {
381         this.dialogData = dialogData
382         this.$refs['refDialog'].resetFields()
383       })
384     },
385     // 关闭编辑弹窗
386     hideDialog() {
387       this.dialogData = {}
388       this.dialogVisible = false
7f89d0 389       // 清空富文本
C 390       // this.rangenum = null
36b711 391     },
L 392     // 提交新增&编辑
393     submitHandle() {
394       this.$refs['refDialog'].validate(valid => {
395         if (valid) {
eaaa5b 396           this.$refs.refUploadImg.runUploadImg((imgUrl) => {
L 397             imgUrl && this.$set(this.dialogData, 'imgUrl', imgUrl)
398             this.submitReq()
399           })
36b711 400         }
L 401       })
402     },
403     // 提交接口
404     submitReq() {
405       var { dialogData } = this
406       var params = {
407         name: dialogData.name,
eaaa5b 408         isUp: dialogData.isUp,
L 409         imgUrl: dialogData.imgUrl
36b711 410       }
L 411
412       if (dialogData.password) params.password = dialogData.password
413
414       var isAdd = dialogData.type === 'add'
7f89d0 415       // TODO url
C 416       var url = isAdd ? 'xxx/add' : 'xxx/edit'
36b711 417
L 418       !isAdd && (params.id = dialogData.id)
419
420       this.postFN({
421         url: url,
422         params: params,
423         mockData: {
424           code: 100,
425           msg: '',
426           data: {}
427         }
428       }, () => {
429         this.$messageSuc('保存成功')
430         this.hideDialog()
b82c1e 431         isAdd ? this.reGetList() : this.getList()
36b711 432       })
eaaa5b 433     },
L 434
435     // 导出列表
436     exportList() {
437       var { keyWord } = this
438       const params = {
439         keyWord: keyWord
440       }
441       this.postFN({
442         url: 'xxxx',
443         params,
444         mockData: {
445           code: 100,
446           msg: '',
447           data: {
448             path: 'xxx'
449           }
450         }
451       }, (inf) => {
452         window.location.href = inf.path
453       })
454     },
455
456     // 清空file
457     clearFile() {
458       this.$refs.upload.value = ''
459     },
460     // 导入
461     fileChange(e) {
462       const file = e.target.files[0]
463       if (!file) {
464         this.clearFile()
465         return
466       }
467
468       // 1. 判断文件类型
469       if (!/\.(xls|xlsx)$/.test(e.target.value)) {
470         this.$messageError('请选择xls或xlsx格式文件')
471         this.clearFile()
472         return
473       }
474
475       // 2. 上传
476       const formData = new FormData()
477       formData.append('file', file)
478       formData.append('virtualPrizeId', this.id)
479       this.postFN({
480         url: 'admin/virtualPrizeItem/importData',
481         header: { 'Content-Type': 'multipart/form-data' },
482         params: formData,
483         mockData: {
484           code: 100,
485           msg: '',
486           data: {}
487         }
488       }, (inf) => {
489         // 部分不成功
490         if (inf && inf.arr && inf.arr.length) {
491           inf.arr.forEach((o) => {
492             this.$messageError(o)
493           })
494         } else {
495           this.$messageSuc('导入成功')
496         }
497         this.clearFile()
498         this.reGetList() // 刷新
499       }, (res) => {
500         this.$messageError('导入失败:' + (res.msg || '未知原因'))
501         this.clearFile()
502         this.reGetList() // 刷新
503       })
36b711 504     }
L 505   }
506 }
507 </script>
508
509 <style lang="scss" scoped>
eaaa5b 510 #upload{
L 511   position: absolute;
512   top: 0;
513   left: 0;
514   width: 100%;
515   height: 100%;
516   opacity: 0;
517   z-index: 1;
518   cursor: pointer;
519   -webkit-appearance: none;
520   appearance: none;
521 }
522 .rel{
523   position: relative;
524   cursor: pointer;
525 }
36b711 526 </style>