list.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. <template>
  2. <view class="user-list">
  3. <!-- #ifdef MP || APP-PLUS -->
  4. <view class="accountTitle">
  5. <view :style="{height:getHeight.barTop+'px'}"></view>
  6. <view class="sysTitle acea-row row-center-wrapper" :style="{height:getHeight.barHeight+'px'}">
  7. <view>用户管理</view>
  8. <text class="iconfont icon-ic_leftarrow" @click="goarrow"></text>
  9. </view>
  10. </view>
  11. <view :style="{height:(getHeight.barTop+getHeight.barHeight)+'px'}"></view>
  12. <!-- #endif -->
  13. <view class="searchCon acea-row row-between-wrapper">
  14. <view class="search acea-row row-middle">
  15. <text class="iconfont icon-ic_search"></text>
  16. <input class="inputs" placeholder='请输入用户昵称/ID' placeholder-class='placeholder' confirm-type='search' name="search"
  17. v-model="keyword" @confirm="searchSubmit"></input>
  18. </view>
  19. <view v-if="storeNum">
  20. <view @click="manageTap" v-if="administer">取消</view>
  21. <view class="edit on acea-row row-center-wrapper" @click="manageTap" v-else>
  22. <text class="iconfont icon-ic_batch"></text>
  23. </view>
  24. </view>
  25. <view class="edit acea-row row-center-wrapper" @click="filterTap" v-if="!administer">
  26. <text class="iconfont icon-ic_sort"></text>
  27. </view>
  28. </view>
  29. <view class="list" v-if="userLists.length">
  30. <checkbox-group @change="checkboxChange">
  31. <view class="acea-row row-middle" v-for="(item, index) in userLists" :key="index">
  32. <!-- #ifndef MP -->
  33. <checkbox class="checkbox" v-if="administer" :value="(item.uid).toString()" :checked="item.checked" />
  34. <!-- #endif -->
  35. <!-- #ifdef MP -->
  36. <checkbox class="checkbox" v-if="administer" :value="item.uid" :checked="item.checked" />
  37. <!-- #endif -->
  38. <view class="item acea-row row-center-wrapper" @click="goDetails(item)">
  39. <view class="pictrue">
  40. <image :src="item.avatar"></image>
  41. </view>
  42. <view class="text">
  43. <view class="top acea-row row-middle">
  44. <view class="name line1">{{item.nickname}}</view>
  45. <view class="svip acea-row row-center-wrapper" v-if="item.isMember == 1">SVIP</view>
  46. <view class="vip acea-row row-center-wrapper" v-if="item.level_status == 1 && item.level_grade">
  47. <text class="iconfont icon-huiyuandengji"></text>
  48. {{item.level}}
  49. </view>
  50. </view>
  51. <view class="phone">{{item.phone}}</view>
  52. <view class="info acea-row row-middle">
  53. <view>积分:<text>{{item.integral}}</text></view>
  54. <view>余额:<text>{{item.now_money}}</text></view>
  55. </view>
  56. </view>
  57. <view v-if="!administer && storeNum" class="iconfont icon-ic_more" @click.stop="openDrawer(item)"></view>
  58. </view>
  59. </view>
  60. </checkbox-group>
  61. </view>
  62. <block v-if="userLists.length == 0 && !loading">
  63. <emptyPage title="暂无用户信息~" src="/statics/images/empty-box.gif"></emptyPage>
  64. </block>
  65. <Loading :loaded="loadend" :loading="loading"></Loading>
  66. <view class="footerH"></view>
  67. <view class="footer acea-row row-between-wrapper" v-if="administer">
  68. <checkbox-group @change="checkboxAllChange">
  69. <checkbox value="all" :checked="isAllSelect" />
  70. <text class='checkAll'>全选({{getIds().length}})</text>
  71. </checkbox-group>
  72. <view class="acea-row row-middle">
  73. <view class="bnt acea-row row-center-wrapper">
  74. <picker @change="bindPickerChange" :range="groupArray" range-key="group_name">
  75. <view>修改分组</view>
  76. </picker>
  77. </view>
  78. <view class="bnt acea-row row-center-wrapper" @click="editLabels">添加标签</view>
  79. <view class="bnt acea-row row-center-wrapper" @click="sendCoupon">发送优惠券</view>
  80. </view>
  81. </view>
  82. <base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
  83. <view class="edit-list rd-t-40rpx">
  84. <view class="item" v-for="(item, index) in editList" :key="index" @tap="editInfo(index)">
  85. <picker @change="bindLevelChange" :range="levelArray" range-key="name" v-if="index == 2">
  86. <view class="uni-input">{{item.name}}</view>
  87. </picker>
  88. <text v-else>{{item.name}}</text>
  89. </view>
  90. </view>
  91. </base-drawer>
  92. <view style="height: 110rpx;"></view>
  93. <footer-page :isWork='storeNum'></footer-page>
  94. <edit-lable ref="lable" :visible='visibleLable' @closeDrawer='lableCloseDrawer'></edit-lable>
  95. <edit-balance ref="balance" :visible='visibleBalance' :type = 'type' :uid='uid' @closeDrawer='balanceCloseDrawer' @successChange='successChange'></edit-balance>
  96. <member ref="member" :visible='visibleMember' :userInfo='userInfo' @closeDrawer='memberCloseDrawer' @successChange='successChange'></member>
  97. <coupon ref="coupon" :visible='visibleCoupon' :uid='uid' @closeDrawer='couponCloseDrawer'></coupon>
  98. <user-filter ref="filter" :types='storeNum' :visible='visibleFilter' :groupArray='groupArray' :levelArray='levelArray' @closeDrawer='filterCloseDrawer' @successChange='filterChange'></user-filter>
  99. </view>
  100. </template>
  101. <script>
  102. import Loading from '@/components/Loading/index'
  103. import emptyPage from '@/components/emptyPage.vue';
  104. import footerPage from '../components/footerPage/index.vue';
  105. import editLable from './components/userLable/index.vue';
  106. import editBalance from './components/editBalance/index.vue';
  107. import member from './components/member/index.vue';
  108. import coupon from './components/coupon/index.vue';
  109. import userFilter from './components/filter/index.vue';
  110. import {
  111. getUserList,
  112. getStoreUserList,
  113. getGroupList,
  114. getStoreGroupList,
  115. postUserUpdate,
  116. getLevelList,
  117. getStoreLevelList
  118. } from "@/api/admin";
  119. import {
  120. mapGetters
  121. } from "vuex";
  122. export default {
  123. components: {
  124. editLable,
  125. editBalance,
  126. member,
  127. coupon,
  128. userFilter,
  129. footerPage,
  130. emptyPage,
  131. Loading
  132. },
  133. computed: mapGetters(["storeNum"]),
  134. data() {
  135. return {
  136. getHeight: this.$util.getWXStatusHeight(),
  137. editList:[
  138. {
  139. name:'修改积分'
  140. },
  141. {
  142. name:'修改余额'
  143. },
  144. {
  145. name:'修改等级'
  146. },
  147. {
  148. name:'赠送会员'
  149. },
  150. {
  151. name:'赠送优惠券'
  152. },
  153. ],
  154. administer:0,
  155. isAllSelect: false,
  156. userLists:[],
  157. visible:false,
  158. visibleLable:false, //标签是否显示
  159. loadTitle: '加载更多',
  160. loading: false,
  161. loadend: false,
  162. limit: 20,
  163. page: 1,
  164. keyword:'', //搜索字段
  165. visibleBalance: false,
  166. type: 0,
  167. visibleMember:false,
  168. visibleCoupon:false,
  169. uid: 0,
  170. groupArray:[],
  171. userInfo:{},
  172. levelArray:[],
  173. visibleFilter:false,
  174. filterData:{
  175. labelIds:'',
  176. groupIds:0,
  177. levelIds:0
  178. }
  179. }
  180. },
  181. onShow() {
  182. },
  183. onLoad() {
  184. this.userList();
  185. this.groupList();
  186. },
  187. methods: {
  188. goarrow(){
  189. uni.navigateBack()
  190. },
  191. filterChange(data){
  192. this.visibleFilter = false
  193. this.filterData = data
  194. this.init();
  195. },
  196. filterCloseDrawer(){
  197. this.visibleFilter = false
  198. },
  199. filterTap(){
  200. this.visibleFilter = true;
  201. this.$refs.filter.productLabel();
  202. this.levelList();
  203. // this.groupList();
  204. },
  205. sendCoupon(){
  206. if(!this.getIds().length){
  207. this.$util.Tips({
  208. title: '请选择商品'
  209. });
  210. return
  211. }
  212. this.visibleCoupon = true;
  213. this.$refs.coupon.userCoupon(1,this.getIds());
  214. },
  215. levelList(){
  216. let funApi = '';
  217. if(this.storeNum){
  218. funApi = getLevelList;
  219. }else{
  220. funApi = getStoreLevelList;
  221. }
  222. funApi().then(res=>{
  223. this.levelArray = res.data.list;
  224. }).catch(err=>{
  225. this.$util.Tips({
  226. title: err
  227. });
  228. })
  229. },
  230. groupList(){
  231. let funApi = '';
  232. if(this.storeNum){
  233. funApi = getGroupList;
  234. }else{
  235. funApi = getStoreGroupList;
  236. }
  237. funApi().then(res=>{
  238. this.groupArray = res.data;
  239. }).catch(err=>{
  240. this.$util.Tips({
  241. title: err
  242. });
  243. })
  244. },
  245. userUpdate(data){
  246. postUserUpdate(data).then(res=>{
  247. this.$util.Tips({
  248. title: res.msg
  249. });
  250. }).catch(err=>{
  251. this.$util.Tips({
  252. title: err
  253. });
  254. })
  255. },
  256. bindLevelChange(e){
  257. this.userUpdate({
  258. type:1,
  259. uid:this.uid,
  260. level:this.levelArray[e.detail.value].id
  261. })
  262. this.init();
  263. },
  264. bindPickerChange(e){
  265. if(!this.getIds().length){
  266. this.$util.Tips({
  267. title: '请选择商品'
  268. });
  269. return
  270. }
  271. this.userUpdate({
  272. type:4,
  273. uid:this.getIds(),
  274. group_id:this.groupArray[e.detail.value].id
  275. })
  276. },
  277. goDetails(item){
  278. uni.navigateTo({
  279. url: '/pages/admin/user/index?uid='+item.uid+'&types='+this.storeNum
  280. })
  281. },
  282. couponCloseDrawer(){
  283. this.visibleCoupon = false
  284. },
  285. memberCloseDrawer(){
  286. this.visibleMember = false
  287. },
  288. balanceCloseDrawer(){
  289. this.visibleBalance = false
  290. },
  291. successChange(){
  292. this.visibleMember = false
  293. this.visibleBalance = false
  294. this.init();
  295. },
  296. //批量编辑标签
  297. editLabels(){
  298. if(!this.getIds().length){
  299. this.$util.Tips({
  300. title: '请选择商品'
  301. });
  302. return
  303. }
  304. this.visibleLable = true
  305. this.visible = false
  306. this.$refs.lable.productLabel({},1,this.getIds());
  307. },
  308. //批量获取id集合
  309. getIds(){
  310. let ids = []
  311. this.userLists.forEach(item=>{
  312. if(item.checked){
  313. ids.push(item.uid)
  314. }
  315. })
  316. ids.slice(0, 100)
  317. return ids
  318. },
  319. init(){
  320. this.userLists = [];
  321. this.page = 1;
  322. this.loadend = false;
  323. this.loading = false;
  324. this.userList();
  325. },
  326. searchSubmit(){
  327. this.init();
  328. },
  329. userList(){
  330. let that = this;
  331. if (this.loading) return;
  332. if (this.loadend) return;
  333. that.loading = true;
  334. that.loadTitle = "";
  335. let funApi = '';
  336. if(this.storeNum){
  337. funApi = getUserList
  338. }else{
  339. funApi = getStoreUserList
  340. }
  341. funApi({
  342. page: that.page,
  343. limit: that.limit,
  344. nickname: that.keyword,
  345. group_id: that.filterData.groupIds,
  346. level: that.filterData.levelIds,
  347. label_id: that.filterData.labelIds
  348. }).then(res=>{
  349. let userLists = res.data.list;
  350. userLists.forEach(item => {
  351. item.checked = false;
  352. })
  353. this.isAllSelect = false
  354. let loadend = userLists.length < that.limit;
  355. that.userLists = that.$util.SplitArray(userLists, that.userLists);
  356. that.$set(that, 'userLists', that.userLists);
  357. that.loadend = loadend;
  358. that.loadTitle = loadend ? '没有更多内容啦~' : '加载更多';
  359. that.page = that.page + 1;
  360. that.loading = false;
  361. }).catch(err=>{
  362. that.loading = false;
  363. that.loadTitle = "加载更多";
  364. })
  365. },
  366. editInfo(index){
  367. switch (index) {
  368. case 0:
  369. this.visible = false
  370. this.visibleBalance = true
  371. this.type = 0
  372. break;
  373. case 1:
  374. this.visible = false
  375. this.visibleBalance = true
  376. this.type = 1
  377. break;
  378. case 2:
  379. this.visible = false
  380. break;
  381. case 3:
  382. this.visible = false
  383. this.visibleMember = true
  384. break;
  385. case 4:
  386. this.visible = false
  387. this.visibleCoupon = true
  388. break;
  389. }
  390. },
  391. lableCloseDrawer(){
  392. this.visibleLable = false
  393. },
  394. openDrawer(item){
  395. this.visible = true
  396. this.uid = item.uid
  397. this.userInfo = item;
  398. this.levelList();
  399. this.$refs.coupon.userCoupon(0);
  400. },
  401. closeDrawer(){
  402. this.visible = false
  403. },
  404. manageTap() {
  405. this.administer = !this.administer;
  406. },
  407. checkboxChange(event) {
  408. let idList = event.detail.value;
  409. this.userLists.forEach((item) => {
  410. if (idList.indexOf(item.uid + '') !== -1) {
  411. item.checked = true;
  412. } else {
  413. item.checked = false;
  414. }
  415. })
  416. if (idList.length == this.userLists.length) {
  417. this.isAllSelect = true;
  418. } else {
  419. this.isAllSelect = false;
  420. }
  421. },
  422. forGoods(val) {
  423. let that = this;
  424. if (!that.userLists.length) return
  425. that.userLists.forEach((item) => {
  426. if (val) {
  427. item.checked = true;
  428. } else {
  429. item.checked = false;
  430. }
  431. })
  432. },
  433. checkboxAllChange(event) {
  434. let value = event.detail.value;
  435. if (value.length) {
  436. if(this.userLists.length>100){
  437. this.$util.Tips({
  438. title: '每次最多只提交100条数据'
  439. });
  440. }
  441. this.isAllSelect = true;
  442. this.forGoods(1)
  443. } else {
  444. this.isAllSelect = false;
  445. this.forGoods(0)
  446. }
  447. },
  448. },
  449. onReachBottom(){
  450. this.userList();
  451. }
  452. }
  453. </script>
  454. <style lang="scss" scoped>
  455. /deep/checkbox .uni-checkbox-input.uni-checkbox-input-checked {
  456. border-color: #2A7EFB !important;
  457. background-color: #2A7EFB !important;
  458. }
  459. /deep/checkbox:not([disabled]) .uni-checkbox-input:hover {
  460. border-color: #d1d1d1 !important;
  461. }
  462. /deep/.empty-page{
  463. margin-top: 20rpx;
  464. }
  465. .accountTitle{
  466. background: #F5F5F5;
  467. position: fixed;
  468. left:0;
  469. top:0;
  470. width: 100%;
  471. z-index: 99;
  472. padding-bottom: 6rpx;
  473. .sysTitle{
  474. width: 100%;
  475. position: relative;
  476. font-weight: 500;
  477. color: #333333;
  478. font-size: 30rpx;
  479. .iconfont{
  480. position: absolute;
  481. font-size: 42rpx;
  482. left:20rpx;
  483. width: 60rpx;
  484. font-weight: 500;
  485. }
  486. }
  487. }
  488. .user-list{
  489. padding: 20rpx 20rpx 0 20rpx;
  490. .searchCon{
  491. .search{
  492. // width: 526rpx;
  493. flex: 1;
  494. height: 72rpx;
  495. background: #FFFFFF;
  496. border-radius: 50rpx;
  497. padding: 0 34rpx;
  498. margin-right: 20rpx;
  499. .iconfont{
  500. color: #999;
  501. font-size: 32rpx;
  502. margin-right: 16rpx;
  503. }
  504. .inputs{
  505. font-size: 28rpx;
  506. width: 100%;
  507. height: 100%;
  508. flex: 1;
  509. }
  510. .placeholder{
  511. color: #ccc;
  512. }
  513. }
  514. .edit{
  515. width: 72rpx;
  516. height: 72rpx;
  517. background: #FFFFFF;
  518. border-radius: 50%;
  519. &.on{
  520. margin-right: 20rpx;
  521. }
  522. .iconfont {
  523. color: #666;
  524. font-size: 36rpx;
  525. }
  526. }
  527. }
  528. .list{
  529. padding-bottom: 20rpx;
  530. margin-top: 32rpx;
  531. /deep/uni-checkbox .uni-checkbox-input{
  532. background-color: #f5f5f5;
  533. margin: 0 20rpx 20rpx 0;
  534. }
  535. /deep/wx-checkbox .wx-checkbox-input{
  536. background-color: #f5f5f5;
  537. margin: 0 20rpx 20rpx 0;
  538. }
  539. .item {
  540. width: 100%;
  541. background-color: #fff;
  542. padding: 30rpx 24rpx;
  543. box-sizing: border-box;
  544. margin-bottom: 20rpx;
  545. border-radius: 24rpx;
  546. position: relative;
  547. flex: 1;
  548. .icon-ic_more{
  549. position: absolute;
  550. right: 20rpx;
  551. top: 30rpx;
  552. color: #999;
  553. font-size: 40rpx;
  554. }
  555. .pictrue{
  556. width: 96rpx;
  557. height: 96rpx;
  558. margin-right: 24rpx;
  559. image {
  560. width: 100%;
  561. height: 100%;
  562. border-radius: 50%;
  563. }
  564. }
  565. .text{
  566. flex: 1;
  567. overflow: hidden;
  568. .top{
  569. .name {
  570. max-width: 230rpx;
  571. font-size: 28rpx;
  572. font-weight: 600;
  573. color: #333333;
  574. font-family: PingFang SC, PingFang SC;
  575. }
  576. .svip {
  577. width: 56rpx;
  578. height: 26rpx;
  579. background: linear-gradient(270deg, #484643 0%, #1F1B17 100%);
  580. border-radius: 100rpx;
  581. font-size: 18rpx;
  582. font-family: PingFang SC, PingFang SC;
  583. font-weight: 600;
  584. color: #FDDAA4;
  585. margin-left: 10rpx;
  586. }
  587. .vip{
  588. width: 64rpx;
  589. // height: 26rpx;
  590. background: #FEF0D9;
  591. border: 1px solid #FACC7D;
  592. border-radius: 50rpx;
  593. font-size: 18rpx;
  594. font-family: PingFang SC, PingFang SC;
  595. font-weight: 500;
  596. color: #DFA541;
  597. margin-left: 10rpx;
  598. .iconfont {
  599. font-size: 20rpx;
  600. margin-right: 4rpx;
  601. }
  602. }
  603. }
  604. .phone{
  605. font-size: 24rpx;
  606. font-family: PingFang SC, PingFang SC;
  607. font-weight: 400;
  608. color: #999999;
  609. margin-top: 4rpx;
  610. }
  611. .info {
  612. font-size: 24rpx;
  613. font-weight: 400;
  614. color: #999999;
  615. margin-top: 4rpx;
  616. text {
  617. color: #333333;
  618. margin-right: 28rpx;
  619. }
  620. }
  621. }
  622. .bottom{
  623. margin-top: 26rpx;
  624. .bnt{
  625. width: 144rpx;
  626. height: 56rpx;
  627. border:1px solid #ccc;
  628. font-size: 24rpx;
  629. font-family: PingFang SC, PingFang SC;
  630. font-weight: 400;
  631. color: #333333;
  632. border-radius: 50rpx;
  633. &~.bnt{
  634. margin-left: 16rpx;
  635. }
  636. &.on{
  637. border-color: #2A7EFB;
  638. background-color: #2A7EFB;
  639. color: #fff;
  640. }
  641. &.up{
  642. border-color: #FF7E00;
  643. color: #FF7E00;
  644. }
  645. }
  646. }
  647. }
  648. }
  649. .footerH {
  650. height: calc(constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  651. height: calc(env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  652. }
  653. .footer {
  654. box-sizing: border-box;
  655. padding: 0 32rpx;
  656. width: 100%;
  657. height: 96rpx;
  658. background-color: #fff;
  659. position: fixed;
  660. bottom: 0;
  661. z-index: 30;
  662. height: calc(96rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  663. height: calc(96rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  664. padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
  665. padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
  666. width: 100%;
  667. left: 0;
  668. /deep/uni-checkbox .uni-checkbox-input{
  669. margin-bottom: 6rpx;
  670. }
  671. .bnt {
  672. width: 160rpx;
  673. height: 64rpx;
  674. border-radius: 50rpx;
  675. border: 1rpx solid #2A7EFB;
  676. color: #2A7EFB;
  677. font-size: 24rpx;
  678. font-family: PingFang SC, PingFang SC;
  679. font-weight: 500;
  680. &~.bnt{
  681. margin-left: 16rpx;
  682. }
  683. }
  684. }
  685. .edit-list{
  686. background-color: #fff;
  687. padding: 45rpx 34rpx;
  688. .item{
  689. font-family: PingFang SC, PingFang SC;
  690. font-weight: 400;
  691. color: #333333;
  692. font-size: 32rpx;
  693. text-align: center;
  694. height: 106rpx;
  695. line-height: 106rpx;
  696. }
  697. }
  698. }
  699. </style>