数字平昌
This commit is contained in:
		| @@ -0,0 +1,64 @@ | ||||
| <template> | ||||
|   <div class="AppActivitiesManagement"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" :permissions="permissions " @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import List from './components/List' | ||||
|   import Detail from './components/Detail' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppResidentIntegrating', | ||||
|     label: '居民积分', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         component: 'List', | ||||
|         params: {}, | ||||
|         include: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       List, | ||||
|       Detail | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (data) { | ||||
|         if (data.type === 'Detail') { | ||||
|           this.component = 'Detail' | ||||
|           this.params = data.params | ||||
|         } | ||||
|  | ||||
|         if (data.type === 'List') { | ||||
|           this.component = 'List' | ||||
|           this.params = data.params | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             if (data.isRefresh) { | ||||
|               this.$refs.component.getList() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppActivitiesManagement { | ||||
|   height: 100%; | ||||
|   background: #F3F6F9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,181 @@ | ||||
| <template> | ||||
|   <ai-detail> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="详情" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <el-row style="margin-bottom: 16px;"> | ||||
|         <div class="card_list"> | ||||
|           <div class="card"> | ||||
|             <h2>姓名</h2> | ||||
|             <p class="color1">{{ info.userName }}</p> | ||||
|           </div> | ||||
|           <div class="card"> | ||||
|             <h2>积分余额</h2> | ||||
|             <p class="color2">{{ info.integral || 0 }}</p> | ||||
|           </div> | ||||
|           <div class="card"> | ||||
|             <h2>已用积分</h2> | ||||
|             <p class="color3">{{ info.usedIntegral || 0 }}</p> | ||||
|           </div> | ||||
|         </div> | ||||
|       </el-row> | ||||
|       <ai-card> | ||||
|         <ai-title slot="title" title="余额变动明细"/> | ||||
|         <template #content> | ||||
|           <ai-search-bar> | ||||
|             <template #left> | ||||
|               <ai-select v-model="search.type" placeholder="请选择类型" @change="search.current = 1, getList()" :selectList="dict.getDict('integralType')"/> | ||||
|             </template> | ||||
|             <template #right> | ||||
|               <ai-download | ||||
|                 :instance="instance" | ||||
|                 :url="`/app/appintegraluser/changeIntegralExport?id=${params.id}`" | ||||
|                 :params="search" | ||||
|                 fileName="余额变动明细" | ||||
|                 :disabled="tableData.length == 0"> | ||||
|                 <el-button size="small">导出</el-button> | ||||
|               </ai-download> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|           <ai-table :tableData="tableData" :total="total" :current.sync="search.current" :size.sync="search.size" | ||||
|                     @getList="getList" :col-configs="colConfigs" :dict="dict"> | ||||
|             <el-table-column slot="changeIntegral" label="变动积分" align="center"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <span>{{ row.integralCalcType == 0 ? '-' : '+' }}{{ row.changeIntegral }}</span> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column slot="eventDesc" label='事件' align="center" show-overflow-tooltip> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <span>{{ row.eventDesc || row.eventName }}</span> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'Detail', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         info: {}, | ||||
|         id: '', | ||||
|         search: { | ||||
|           current: 1, | ||||
|           size: 10, | ||||
|           type: '' | ||||
|         }, | ||||
|         total: 0, | ||||
|         tableData: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       colConfigs() { | ||||
|         return [ | ||||
|           {prop: "doTime", label: '时间', align: "left", width: "200px"}, | ||||
|           {prop: "integralType", label: '类型', align: "center", dict: "integralType"}, | ||||
|           {slot: "changeIntegral"}, | ||||
|           {prop: "nowIntegral", label: '剩余积分', align: "center" }, | ||||
|           {slot: "eventDesc"}, | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       console.log(this.params) | ||||
|       this.dict.load('integralType').then(() => { | ||||
|         this.getInfo() | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getInfo (id) { | ||||
|         this.instance.post(`/app/appintegraluser/girdDetail?id=${this.params.id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.info = res.data | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appintegraluser/getChangeDetail`, null, { | ||||
|           params: { | ||||
|             ...this.search, | ||||
|             id: this.params.id | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'List', | ||||
|           isRefresh: !!isRefresh | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .card_list { | ||||
|     display: flex; | ||||
|  | ||||
|     .card { | ||||
|       flex: 1; | ||||
|       height: 96px; | ||||
|       background: #FFFFFF; | ||||
|       box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.1500); | ||||
|       border-radius: 4px; | ||||
|       margin-right: 20px; | ||||
|       padding: 16px 24px; | ||||
|       box-sizing: border-box; | ||||
|  | ||||
|       h2 { | ||||
|         color: #888888; | ||||
|         font-weight: 600; | ||||
|         font-size: 16px; | ||||
|       } | ||||
|  | ||||
|       p { | ||||
|         margin-top: 8px; | ||||
|         font-size: 24px; | ||||
|         font-weight: 600; | ||||
|       } | ||||
|  | ||||
|       .color1 { | ||||
|         color: #2891FF; | ||||
|       } | ||||
|  | ||||
|       .color2 { | ||||
|         color: #22AA99; | ||||
|       } | ||||
|  | ||||
|       .color3 { | ||||
|         color: #F8B425; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .card:last-child { | ||||
|       margin-right: 0; | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -0,0 +1,277 @@ | ||||
| <template> | ||||
|   <ai-list class="notice"> | ||||
|     <ai-title slot="title" title="居民积分" v-model="search.areaId" isShowBottomBorder isShowArea :hideLevel="hideLevel - 1" @change="search.current = 1, getList()"></ai-title> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar class="search-bar"> | ||||
|         <template #left> | ||||
|           <el-button type="primary" size="small" icon="iconfont iconAdd" @click="changeIntegral('',0)"> 批量调整积分</el-button> | ||||
|           <ai-download | ||||
|             :instance="instance" | ||||
|             url="/app/appwechatuserqujing/export" | ||||
|             :params="params" | ||||
|             v-if="permissions('app_appwechatuserqujing_export')" | ||||
|             fileName="居民积分" | ||||
|              :disabled="tableData.length == 0"> | ||||
|             <el-button icon="iconfont iconExported" :disabled="tableData.length == 0">导出</el-button> | ||||
|           </ai-download> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <el-input | ||||
|             v-model="search.idNumber" | ||||
|             class="search-input" | ||||
|             size="small" | ||||
|             v-throttle="() => {search.current = 1, getList()}" | ||||
|             placeholder="姓名/身份证/手机号" | ||||
|             clearable | ||||
|             @clear="search.current = 1, search.idNumber = '', getList()" | ||||
|             suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="total" | ||||
|         style="margin-top: 6px;" | ||||
|         :current.sync="search.current" | ||||
|         :size.sync="search.size" | ||||
|         @getList="getList"> | ||||
|         <el-table-column slot="options" width="120px" fixed="right" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" @click="toDetail(row.integralUserId)">详情</el-button> | ||||
|               <el-button type="text" @click="changeIntegral(row,1)">调整积分</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|       <ai-dialog | ||||
|         title="调整积分" | ||||
|         :visible.sync="dialog" | ||||
|         :destroyOnClose="true" | ||||
|         width="720px" | ||||
|         @onConfirm="onConfirm" | ||||
|         @closed="form={},chooseUserList=[]"> | ||||
|         <el-form ref="form" :model="form" :rules="rules" label-width="80px"> | ||||
|           <el-form-item label="选择人员" prop="ids" v-if="!isEdit"> | ||||
|             <ai-person-select :instance="instance" keys="openId" customRightText :customClicker="true" :chooseUserList="chooseUserList" | ||||
|                 url="/app/appwechatuserqujing/listByFdAppletUser" headerTitle="用户列表" | ||||
|                 :isMultiple="true" dialogTitle="选择" @selectPerson="selectPerson" class="aipersonselect"> | ||||
|               <template name="option" v-slot:option="{ item }"> | ||||
|                 <span class="iconfont iconProlife">{{ item.realName }}</span> | ||||
|                 <ai-id mode="show" :show-eyes="false" :value="item.idNumber"/> | ||||
|               </template> | ||||
|             </ai-person-select> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="调整说明" prop="eventDesc"> | ||||
|             <el-input v-model="form.eventDesc" placeholder="请输入..." type="textarea" :rows="4" show-word-limit | ||||
|                       maxlength="100"></el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="类型" prop="integralCalcType"> | ||||
|             <ai-select v-model="form.integralCalcType" :selectList="dict.getDict('integralCalcType')"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="积分" prop="integral"> | ||||
|             <el-input v-model.trim="form.integral" placeholder="请输入正数" size="small"></el-input> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   export default { | ||||
|     name: 'List', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         search: { | ||||
|           current: 1, | ||||
|           size: 10, | ||||
|           idNumber: '', | ||||
|           areaId: '' | ||||
|         }, | ||||
|         form: { | ||||
|           ids: [], | ||||
|           eventDesc: "", | ||||
|           enclosure: "", | ||||
|           integralCalcType: "", | ||||
|           integral: '' | ||||
|         }, | ||||
|         dialog: false, | ||||
|         chooseUserList: [], | ||||
|         total: 0, | ||||
|         isEdit: false, | ||||
|         colConfigs: [ | ||||
|           { prop: 'realName',  label: '姓名', align: 'left', width: '200px' }, | ||||
|           { prop: 'phone',  label: '手机号', align: 'center' }, | ||||
|           { prop: 'idNumber', label: '身份证号', align: 'center' }, | ||||
|           { prop: 'areaName', label: '所属地区', align: 'center' }, | ||||
|           { prop: 'girdName', label: '所属网格', align: 'center' }, | ||||
|           { prop: 'integral', label: '剩余积分', align: 'center' }, | ||||
|           { prop: 'usedIntegral', label: '已用积分', align: 'center' } | ||||
|         ], | ||||
|         tableData: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']), | ||||
|  | ||||
|       hideLevel () { | ||||
|         return this.user.info.areaList.length || 0 | ||||
|       }, | ||||
|  | ||||
|       params () { | ||||
|         return { | ||||
|           ...this.search, | ||||
|           size: 1000 | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       rules() { | ||||
|         return { | ||||
|           ids: [{required: true, message: '请选择人员', trigger: 'blur'}], | ||||
|           eventDesc: [{required: true, message: '请输入调整说明', trigger: 'blur'}], | ||||
|           integralCalcType: [{required: true, message: '请选择类型', trigger: 'blur'}], | ||||
|           integral: [{required: true, message: '请输入积分', trigger: 'blur' }, | ||||
|           {pattern: /^([1-9]\d*|0)(\.\d{1,2})?$/, message: '请输入正数且最多只能保留两位小数'}], | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created() { | ||||
|       this.search.areaId = this.user.info.areaId | ||||
|       this.dict.load('integralCalcType').then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appwechatuserqujing/listByFdAppletUser`, null, { | ||||
|           params: { | ||||
|             ...this.search, | ||||
|             areaId: this.search.areaId | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       selectPerson(val) { | ||||
|         if (val) { | ||||
|           this.personList = val | ||||
|           this.form.ids = [...this.personList.map(e => e.openId)] | ||||
|         } else { | ||||
|           this.form.ids = this.chooseUserList.map(e => e.openId) | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       changeIntegral(row,type) { | ||||
|         this.isEdit = false | ||||
|         if(type==0) { | ||||
|           this.dialog = true | ||||
|         } else if(type ==1) { | ||||
|           this.isEdit = true | ||||
|           this.chooseUserList = [{ | ||||
|             openId: row.openId, | ||||
|             name: row.realName | ||||
|           }] | ||||
|           this.form = { | ||||
|             ids: this.chooseUserList.map(e => e.openId) | ||||
|           } | ||||
|  | ||||
|           this.dialog = true | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       changeTableSort(col) { | ||||
|         if(col.prop === 'integral') { // 剩余积分 | ||||
|           this.search.sortFiled = 0 | ||||
|           if(col.order === 'ascending') { | ||||
|             this.search.sortRule = true | ||||
|           } else if(col.order === 'descending') { | ||||
|             this.search.sortRule = false | ||||
|           } else if(col.order === null) { | ||||
|             this.search.sortRule = '' | ||||
|           } | ||||
|         } else if(col.prop === 'totalIntegral') {  // 累计积分 | ||||
|           this.search.sortFiled = 1 | ||||
|           if(col.order === 'ascending') { | ||||
|             this.search.sortRule = true | ||||
|           } else if(col.order === 'descending') { | ||||
|             this.search.sortRule = false | ||||
|           } else if(col.order === null) { | ||||
|             this.search.sortRule = '' | ||||
|           } | ||||
|         } else if(col.prop === 'usedIntegral') {  // 已用积分 | ||||
|           this.search.sortFiled = 2 | ||||
|           if(col.order === 'ascending') { | ||||
|             this.search.sortRule = true | ||||
|           } else if(col.order === 'descending') { | ||||
|             this.search.sortRule = false | ||||
|           } else if(col.order === null) { | ||||
|             this.search.sortRule = '' | ||||
|           } | ||||
|         } | ||||
|         this.getList() | ||||
|       }, | ||||
|  | ||||
|       onConfirm() { | ||||
|         if(this.flag) return | ||||
|  | ||||
|         if(this.form.file?.length) { | ||||
|           this.form.enclosure = this.form.file[0].url | ||||
|         } | ||||
|         this.$refs.form.validate((valid)=> { | ||||
|           if(valid) { | ||||
|             this.flag = true | ||||
|             this.instance.post(`/app/appintegraluser/changeIntegral`,{ | ||||
|               ids: this.form.ids, | ||||
|               eventDesc: this.form.eventDesc, | ||||
|               enclosure: this.form.enclosure,   // 附件 | ||||
|               integralCalcType: this.form.integralCalcType, | ||||
|               integral: this.form.integral, | ||||
|               integralUserType: 3 | ||||
|             }).then(res => { | ||||
|               if(res?.code == 0) { | ||||
|                 this.$message.success('调整积分成功') | ||||
|                 setTimeout(() =>{ | ||||
|                   this.dialog = false | ||||
|                   this.getList() | ||||
|                   this.flag = false | ||||
|                 }, 600) | ||||
|               } else { | ||||
|                 this.flag = false | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|  | ||||
|       }, | ||||
|  | ||||
|       toDetail(id) { | ||||
|         this.$emit('change', { | ||||
|           type: 'Detail', | ||||
|           params: { | ||||
|             id: id || '' | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user