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