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