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