long
2021-07-15 eaaa5b7839f08ddae008bd9fba3fa432b689b9af
提交 | 用户 | 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
62     <el-table :data="list" max-height="500px" stripe>
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 {
185       showSearch: true, // 是否显示搜索区
7f89d0 186       keyWord: '', // 搜索区字段,可自行扩展其余字段
36b711 187
7f89d0 188       // TODO
C 189       objectName: 'xx', // 对象名称,用于删除提示、启用提示、弹窗标题等
190
191       // 数据列表
36b711 192       list: [],
L 193
194       // 弹窗数据
195       dialogVisible: false,
196       dialogData: {},
7f89d0 197
C 198       // 富文本编辑器
199       // rangenum: null,
36b711 200
L 201       // 分页 ↓↓↓↓↓↓↓↓↓↓
202       total: 0,
203       pageNum: 1,
204       pageSize: 20,
205       // 分页 ↑↑↑↑↑↑↑↑↑↑
206
207       // 表单校验
208       rules: {
209         name: [
210           { required: true, message: '名称不能为空', trigger: 'change' }
211         ],
212         isUp: [
213           { required: true, message: '是否上架不能为空', trigger: 'change' }
eaaa5b 214         ],
L 215         uploadImgs: [
216           { required: true, message: '图片不能为空' }
36b711 217         ]
L 218       }
219     }
220   },
221   mounted() {
222     this.init()
223   },
224   methods: {
225     // 初始化
226     init() {
227       this.getList()
228     },
229
7f89d0 230     // ========== 富文本相关
C 231     // 富文本编辑器的内容赋值
232     // catchData(content) {
233     //   if (content === '<p><br></p>') content = ''
234     //   try {
235     //     const currentRange = window.getSelection().getRangeAt(0)
236     //     this.rangenum = currentRange
237     //   } catch (e) {
238     //
239     //   }
240     //   this.$set(this.dialogData, 'content', content)
241     //   this.$refs[this.formName].validateField('content')
242     // },
243     // ========== 富文本相关
244
36b711 245     // 获取列表
L 246     getList() {
247       var { pageNum, pageSize, keyWord } = this
248       this.postFN({
7f89d0 249         // TODO url
36b711 250         url: 'xxx',
L 251         params: {
252           pageNum: pageNum,
253           pageSize: pageSize,
254           keyWord: keyWord
255         },
256         mockData: {
257           code: 100,
258           msg: '',
259           data: {
260             list: [{
261               id: 'xxx',
262               index: 1,
263               name: '超级管理员',
1dcdda 264               createTime: '2020-08-09 10:10:10',
L 265               adviceInfo: '啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦'
36b711 266             }],
L 267             total: 100
268           }
269         }
270       }, (inf) => {
7f89d0 271         // 测试用
36b711 272         for (var i = 0; i < 19; i++) {
L 273           inf.list.push({
274             id: 'xxx',
275             index: 1,
276             name: '超级管理员',
277             createTime: '2020-08-09 10:10:10'
278           })
279         }
280         this.list = inf.list || []
281         this.total = inf.total
282       })
283     },
284     // 重新获取列表
285     reGetList() {
286       this.pageNum = 1
287       this.getList()
288     },
289     // 重置
290     resetHandle() {
291       this.keyWord = ''
292       this.reGetList()
293     },
294     // 删除
295     handleDelete(item) {
296       // 打开二次确认弹窗
297       this.$confirm('是否确认删除该角色?', '提示', {
298         confirmButtonText: '确定',
299         cancelButtonText: '取消',
300         type: 'warning'
301       }).then(() => {
302         // 确定回调
7f89d0 303         // TODO url
36b711 304         this.postFN({
L 305           url: 'xxx',
306           params: {
307             id: item.id
308           },
309           mockData: {
310             code: 100,
311             msg: '',
312             data: {}
313           }
314         }, () => {
315           this.getList()
316           this.$messageSuc('删除成功')
317         })
318       }).catch(() => {})
319     },
320     // 修改是否上架 todo
321     handleUpChange(item) {
322       const text = item.isUp === 1 ? '上架' : '下架'
323       this.$confirm('确认要' + text + '该角色吗?', '提示', {
324         confirmButtonText: '确定',
325         cancelButtonText: '取消',
326         type: 'warning'
327       }).then(() => {
328         this.postFN({
329           url: 'xxx',
7f89d0 330           // TODO url
36b711 331           params: {
L 332             id: item.id
333           },
334           mockData: {
335             code: 100,
336             msg: '',
337             data: {}
338           }
339         }, () => {
340           this.$messageSuc(text + '成功')
4dde14 341         }, (res) => {
L 342           item.isUp = item.isUp === 1 ? 0 : 1
343           this.$messageError(res.msg)
36b711 344         })
L 345       }).catch(() => {
346         item.isUp = item.isUp === 1 ? 0 : 1
347       })
348     },
349
350     // 打开新增弹窗
351     showAddDialog() {
352       var dialogData = {
353         type: 'add',
354         isUp: 1
355       }
356       this.dialogVisible = true
357       this.$nextTick(() => {
358         this.dialogData = dialogData
359         this.$refs['refDialog'].resetFields()
360       })
361     },
362     // 打开编辑弹框
363     showEditDialog(item) {
364       var dialogData = {
365         type: 'edit',
366         ...item
367       }
eaaa5b 368       dialogData.uploadImgs = [{ url: item.imgUrl, status: 'success' }]
L 369
36b711 370       console.log('dialogData', dialogData)
L 371       this.dialogVisible = true
372       this.$nextTick(() => {
373         this.dialogData = dialogData
374         this.$refs['refDialog'].resetFields()
375       })
376     },
377     // 关闭编辑弹窗
378     hideDialog() {
379       this.dialogData = {}
380       this.dialogVisible = false
7f89d0 381       // 清空富文本
C 382       // this.rangenum = null
36b711 383     },
L 384     // 提交新增&编辑
385     submitHandle() {
386       this.$refs['refDialog'].validate(valid => {
387         if (valid) {
eaaa5b 388           this.$refs.refUploadImg.runUploadImg((imgUrl) => {
L 389             imgUrl && this.$set(this.dialogData, 'imgUrl', imgUrl)
390             this.submitReq()
391           })
36b711 392         }
L 393       })
394     },
395     // 提交接口
396     submitReq() {
397       var { dialogData } = this
398       var params = {
399         name: dialogData.name,
eaaa5b 400         isUp: dialogData.isUp,
L 401         imgUrl: dialogData.imgUrl
36b711 402       }
L 403
404       if (dialogData.password) params.password = dialogData.password
405
406       var isAdd = dialogData.type === 'add'
7f89d0 407       // TODO url
C 408       var url = isAdd ? 'xxx/add' : 'xxx/edit'
36b711 409
L 410       !isAdd && (params.id = dialogData.id)
411
412       this.postFN({
413         url: url,
414         params: params,
415         mockData: {
416           code: 100,
417           msg: '',
418           data: {}
419         }
420       }, () => {
421         this.$messageSuc('保存成功')
422         this.hideDialog()
b82c1e 423         isAdd ? this.reGetList() : this.getList()
36b711 424       })
eaaa5b 425     },
L 426
427     // 导出列表
428     exportList() {
429       var { keyWord } = this
430       const params = {
431         keyWord: keyWord
432       }
433       this.postFN({
434         url: 'xxxx',
435         params,
436         mockData: {
437           code: 100,
438           msg: '',
439           data: {
440             path: 'xxx'
441           }
442         }
443       }, (inf) => {
444         window.location.href = inf.path
445       })
446     },
447
448     // 清空file
449     clearFile() {
450       this.$refs.upload.value = ''
451     },
452     // 导入
453     fileChange(e) {
454       const file = e.target.files[0]
455       if (!file) {
456         this.clearFile()
457         return
458       }
459
460       // 1. 判断文件类型
461       if (!/\.(xls|xlsx)$/.test(e.target.value)) {
462         this.$messageError('请选择xls或xlsx格式文件')
463         this.clearFile()
464         return
465       }
466
467       // 2. 上传
468       const formData = new FormData()
469       formData.append('file', file)
470       formData.append('virtualPrizeId', this.id)
471       this.postFN({
472         url: 'admin/virtualPrizeItem/importData',
473         header: { 'Content-Type': 'multipart/form-data' },
474         params: formData,
475         mockData: {
476           code: 100,
477           msg: '',
478           data: {}
479         }
480       }, (inf) => {
481         // 部分不成功
482         if (inf && inf.arr && inf.arr.length) {
483           inf.arr.forEach((o) => {
484             this.$messageError(o)
485           })
486         } else {
487           this.$messageSuc('导入成功')
488         }
489         this.clearFile()
490         this.reGetList() // 刷新
491       }, (res) => {
492         this.$messageError('导入失败:' + (res.msg || '未知原因'))
493         this.clearFile()
494         this.reGetList() // 刷新
495       })
36b711 496     }
L 497   }
498 }
499 </script>
500
501 <style lang="scss" scoped>
eaaa5b 502 #upload{
L 503   position: absolute;
504   top: 0;
505   left: 0;
506   width: 100%;
507   height: 100%;
508   opacity: 0;
509   z-index: 1;
510   cursor: pointer;
511   -webkit-appearance: none;
512   appearance: none;
513 }
514 .rel{
515   position: relative;
516   cursor: pointer;
517 }
36b711 518 </style>