users.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. <template>
  2. <view class="column" style="height: calc(100% - 20rpx) ;">
  3. <view class="top " >
  4. <u-search placeholder="输入姓名/昵称搜索" bgColor='#F8F8FC'
  5. v-model="searchContent" @custom="search()" @search="search()"></u-search>
  6. <view class="justify-around fs28">
  7. <view v-for="(item,index) in tabs" :key="index" :class="act==index?'active':'notact'"
  8. @click="tabact(index)" class="flex-1 center ptb20">{{item}}</view>
  9. <view v-show="act==1" @click="selectact=!selectact" :class="selectact?'active':''"
  10. class="flex-1 center ptb20">批量</view>
  11. </view>
  12. </view>
  13. <view v-if='list.length<1' class="center mt60" style="color: #666;">暂无用户</view>
  14. <scroll-view scroll-y class="indexes flex-1 pb60" :scroll-into-view="'indexes-'+ listCurID" :style="[{height:'calc(100vh - 300rpx)'}]"
  15. :scroll-with-animation="true" :enable-back-to-top="true" >
  16. <view v-for="(item,index) in list" :key="index">
  17. <view :class="'indexItem-' + item.firstLetter" :id="'indexes-' + item.firstLetter" :data-index="item.firstLetter" @click.passive.stop>
  18. <view class="zm">{{item.firstLetter}}</view>
  19. <view class="user-list">
  20. <view class="user-item justify-start" v-for="(subitem,indexs) in item.list"
  21. @click="navTo(subitem)" :key="indexs">
  22. <u-checkbox-group @change="changeitem(subitem.userId)" v-if="selectact">
  23. <u-checkbox :checked="subitem.checked" shape="circle" activeColor="#1773ff" :name="subitem.userId"
  24. labelColor="#1773ff" />
  25. </u-checkbox-group>
  26. <view class="bgf p20 radius16 flex-1">
  27. <view class="justify-between align-center">
  28. <view class="justify-start align-center">
  29. <view class="avatar" >
  30. <image class="img" :src="subitem.avatar?(baseUrl+subitem.avatar):avatar" mode="aspectFill"></image>
  31. </view>
  32. <view class="content">
  33. <view class="name">
  34. {{subitem.nickName}}
  35. </view>
  36. <view class="dept justify-start align-center">
  37. <u-icon name="phone"></u-icon><view>{{subitem.phoneNumber}}</view> </view>
  38. <view class="dept">注册时间:{{subitem.registerTime}}</view>
  39. </view>
  40. </view>
  41. <view class="base-color fs24" v-if="subitem.status==0">未禁用</view>
  42. <view class="base-color-red fs24" v-else>禁用</view>
  43. </view>
  44. <view class="justify-between align-center mt10" @click.passive.stop>
  45. <view>
  46. <text class="base-color-9 ml10 fs24">部门:{{subitem.deptName?subitem.deptName:''}}</text>
  47. <view class="fs24 mt10 justify-start align-center" style="color: #115296;">
  48. <text class="base-color-9 ml10">岗位:{{subitem.postname?subitem.postname:''}}</text>
  49. <text class="base-color-9 ml20">角色:{{subitem.rolesname?subitem.rolesname:''}}</text>
  50. </view>
  51. </view>
  52. <!-- <view class="fs24 base-color-red mr10 bor-red
  53. base-bg-false plr20 radius40 ptb4">已禁用</view> -->
  54. <view class="fs24 base-color mr10 bor-blue h52 lh50
  55. base-bg-sure plr20 radius40 " style="width: fit-content;" v-if="subitem.isAudit==1">已审核</view>
  56. <view class="fs24 base-color-red mr10 bor-red h52 lh50
  57. base-bg-false plr20 radius40 " style="width: fit-content;z-index: 999;" @click="getidshen(subitem.userId)"
  58. v-else-if="subitem.isAudit==0&&!selectact">待审核</view>
  59. </view>
  60. </view>
  61. </view>
  62. </view>
  63. </view>
  64. </view>
  65. </scroll-view>
  66. <view class="indexBar" :style="[{height:'calc(100vh - 88rpx)'}]">
  67. <view class="indexBar-box" @touchstart="tStart" @touchend="tEnd" @touchmove.stop="tMove">
  68. <view class="indexBar-item" v-for="(item,index) in list" :key="index" :id="index"
  69. @touchstart="getCur" @touchend="setCur"> {{item.firstLetter}}</view>
  70. </view>
  71. </view>
  72. <view class="justify-between base-bg-f foot-select " v-if="selectact">
  73. <view class="align-center justify-between " v-if="selectact">
  74. <u-checkbox-group @change="selectAll">
  75. <u-checkbox :checked="isSelectAll" shape="circle" activeColor="#1773ff" :name="true"
  76. label="全选" labelColor="#333" />
  77. <text class="fs24 base-color-9 ml12">已选{{ selectedUsers.length }}个</text>
  78. <!-- {{selectedCount}} -->
  79. </u-checkbox-group>
  80. </view>
  81. <view class="justify-center ">
  82. <button class="base-bg-f radius100 base-color-red h62 ml10 fs28 lh60"
  83. style="border: #ef4c50 solid 2rpx;"
  84. @click="batchApprove">通过审核</button>
  85. </view>
  86. </view>
  87. <!--选择显示-->
  88. <view v-show="!hidden" class="indexToast">
  89. {{listCur}}
  90. </view>
  91. <u-popup :show="showcommpany" mode="center" round="16">
  92. <view class="bgf w600 h600 p40 radius16" style="max-height: 600rpx;">
  93. <view class="center bold fs32">设置销售员信息</view>
  94. <view class="justify-center align-center mtb30">
  95. <view class="mr40 fs32 base-color-6">部门:</view>
  96. <u-input
  97. placeholder="选择部门"
  98. border="surround"
  99. v-model="valueb"
  100. @focus="showbumen()"
  101. ></u-input>
  102. </view>
  103. <view class="justify-center align-center mtb30">
  104. <view class="mr40 fs32 base-color-6">岗位:</view>
  105. <view class="flex-1 u-border p16 radius8" @click="showgang=!showgang">
  106. <view class="fs28" style="color: #000;">{{valuea}}</view>
  107. <view class="fs28" style="color: #c0c4cc;" v-if="valueid.length==0">选择岗位</view>
  108. </view>
  109. </view>
  110. <view class="justify-center align-center mtb30">
  111. <view class="mr40 fs32 base-color-6">角色:</view>
  112. <view class="flex-1 u-border p16 radius8" @click="showjuese=!showjuese">
  113. <view class="fs28" style="color: #000;">{{valuej}}</view>
  114. <view class="fs28" style="color: #c0c4cc;" v-if="valuej.length==0">选择角色</view>
  115. </view>
  116. </view>
  117. <view class="justify-around align-center mt50 ">
  118. <view class="quxiao" @click="showcommpany=!showcommpany">取消</view>
  119. <view class="queren" @click="confirmbchange">通过审核</view>
  120. </view>
  121. <tki-tree ref="tkitree" :range="columnb" confirmColor="#4e8af7" :selectParent="true" @confirm="confirmb"/>
  122. <u-popup :show="showgang" @close="showgang=!showgang" :closeOnClickOverlay='true'>
  123. <view class="center bold fs36 pt40">请选择岗位</view>
  124. <view class="justify-start align-center warpbox mt40 p20">
  125. <view v-for="(item,index) in postlist" :key="item.postId" class="mlr10 mt10">
  126. <u-tag :text="item.postName" :plain="!item.checked" :name="index"
  127. @click="choosechangeTag"></u-tag>
  128. </view>
  129. </view>
  130. <view class="justify-around align-center mt50 ">
  131. <view class="quxiao" @click="showgang=!showgang">取消</view>
  132. <view class="queren" @click="postconfirm">确定</view>
  133. </view>
  134. </u-popup>
  135. <u-popup :show="showjuese" @close="showjuese=!showjuese" :closeOnClickOverlay='true'>
  136. <view class="center bold fs36 pt40">请选择角色</view>
  137. <view class="justify-start align-center warpbox mt40 p20">
  138. <view v-for="(item,index) in rolelist" :key="item.roleId" class="mlr10 mt10">
  139. <u-tag :text="item.roleName" :plain="!item.checked" :name="index"
  140. @click="choosechangerole"></u-tag>
  141. </view>
  142. </view>
  143. <view class="justify-around align-center mt50 ">
  144. <view class="quxiao" @click="showjuese=!showjuese">取消</view>
  145. <view class="queren" @click="roleconfirm">确定</view>
  146. </view>
  147. </u-popup>
  148. </view>
  149. </u-popup>
  150. </view>
  151. </template>
  152. <script>
  153. import {getAllUsers,querydepartment,querypost,modifysaleNews,queryrole} from '@/api/user.js';
  154. import {subsalesaudit} from '@/api/courseManage.js';
  155. import tkiTree from "@/components/tki-tree/tki-tree.vue"
  156. export default {
  157. components: {tkiTree},
  158. data() {
  159. return {
  160. baseUrl:uni.getStorageSync('requestPath'),
  161. avatar:this.$store.state.imgpath+"/app/images/default.png",
  162. CustomBar: 0,
  163. hidden: true,
  164. listCurID: '',
  165. list: [],
  166. listCur: '',
  167. searchContent:"",
  168. tabs:['已审核','未审核'],
  169. act:0,
  170. selectact:false,
  171. isSelectAll:false,
  172. selectedUsers:[],
  173. isAudits:1,
  174. ids:'',
  175. showcommpany:false,
  176. columnb: [
  177. ['11', '22', '33']
  178. ],
  179. postlist:{},
  180. showgang:false,
  181. showjuese:false,
  182. valuea:'',
  183. valueb:'',
  184. actpost:[],
  185. valueid:'',
  186. valueidbu:'',
  187. xuanid:[],
  188. valuej:'',
  189. rolelist:[],
  190. roleid:[],
  191. seluserids:[]
  192. }
  193. },
  194. onLoad() {
  195. this.getUser();
  196. this.getdepartment()
  197. this.getpostlist()
  198. this.getrolelist()
  199. },
  200. onReady() {
  201. let that = this;
  202. uni.createSelectorQuery().select('.indexBar-box').boundingClientRect(function(res) {
  203. that.boxTop = res.top
  204. }).exec();
  205. uni.createSelectorQuery().select('.indexes').boundingClientRect(function(res) {
  206. that.barTop = res.top
  207. }).exec()
  208. },
  209. methods: {
  210. roleconfirm(){
  211. this.roleid = this.rolelist.filter(item => item.checked).map(v => v.roleId).join(",")
  212. this.valuej = this.rolelist.filter(item => item.checked).map(v => v.roleName).join(',')
  213. this.showjuese=!this.showjuese
  214. },
  215. choosechangerole(i){
  216. this.rolelist[i].checked = !this.rolelist[i].checked
  217. },
  218. showbumen(){
  219. this.$refs.tkitree._show();
  220. },
  221. confirmbchange(){
  222. console.log(this.valueb.length,this.xuanid)
  223. if(this.valueb.length==0){
  224. uni.showToast({
  225. icon: 'none',
  226. title: '请选择部门'
  227. })
  228. return
  229. }
  230. if(this.xuanid.length==0){
  231. uni.showToast({
  232. icon: 'none',
  233. title: '请选择部门'
  234. })
  235. return
  236. }
  237. if(this.valuej.length==0){
  238. uni.showToast({
  239. icon: 'none',
  240. title: '请选择角色'
  241. })
  242. return
  243. }
  244. const data={
  245. companyUserIds:this.ids,
  246. deptId:this.valueidbu,
  247. postIds:this.valueid,
  248. roleIds:this.roleid
  249. }
  250. modifysaleNews(data).then(res=>{
  251. console.log('设置信息',res)
  252. if(res.code==200){
  253. // uni.showToast({
  254. // icon: 'none',
  255. // title: '成功'
  256. // })
  257. this.xuanid=[]
  258. setTimeout(()=>{
  259. this.subsalesaudits()
  260. },100)
  261. }else{
  262. uni.showToast({
  263. title: res.msg,
  264. icon: 'none',
  265. });
  266. }
  267. })
  268. },
  269. getallList(){
  270. this.valueidbu=[]
  271. this.valueid=[]
  272. this.valueb=''
  273. this.valuea=''
  274. this.ids=''
  275. },
  276. postconfirm(){
  277. this.xuanid=this.postlist.filter(item => item.checked).map(v => v.postId)
  278. this.valueid = this.postlist.filter(item => item.checked).map(v => v.postId).join(",")
  279. this.valuea = this.postlist.filter(item => item.checked).map(v => v.postName).join(',')
  280. this.showgang=!this.showgang
  281. },
  282. choosechangeTag(i) {
  283. console.log(this.postlist[i].checked )
  284. this.postlist[i].checked = !this.postlist[i].checked
  285. },
  286. getdepartment(){
  287. querydepartment().then(res=>{
  288. if(res.code==200){
  289. this.columnb=res.data
  290. // console.log('部门',res)
  291. }
  292. })
  293. },
  294. getpostlist(){
  295. querypost().then(res=>{
  296. if(res.code==200){
  297. this.postlist = res.data.map(item => {
  298. return {
  299. ...item,
  300. checked: false,
  301. }
  302. })
  303. console.log('岗位',res)
  304. }
  305. })
  306. },
  307. getrolelist(){
  308. queryrole().then(res=>{
  309. if(res.code==200){
  310. this.rolelist = res.data.map(item => {
  311. return {
  312. ...item,
  313. checked: false,
  314. }
  315. })
  316. // console.log('岗位',res)
  317. }
  318. })
  319. },
  320. confirma(e){
  321. this.showgang = !this.showgang
  322. this.valuea=e.value[0]
  323. console.log(e)
  324. },
  325. confirmb(e){
  326. this.valueb=e[0].label
  327. this.valueidbu=e[0].id
  328. console.log(e[0])
  329. },
  330. getidshen(id){
  331. console.log(id)
  332. this.getallList()
  333. this.ids=id
  334. this.seluserids[0]=id
  335. this.showcommpany=!this.showcommpany
  336. },
  337. batchApprove(){
  338. if (this.selectedUsers.length === 0) {
  339. uni.showToast({
  340. title: '请先选择用户',
  341. icon: 'none',
  342. });
  343. return;
  344. }
  345. this.ids=this.selectedUsers.join(',')
  346. // this.ids=this.selectedUsers
  347. this.showcommpany=!this.showcommpany
  348. // this.subsalesaudits()
  349. // this.confirmbchange()
  350. },
  351. subsalesaudits(){
  352. const data={
  353. userIds:this.seluserids
  354. }
  355. subsalesaudit(this.seluserids).then(res=>{
  356. console.log("subsalesaudits=====",res)
  357. if(res.code==200){
  358. uni.showToast({
  359. title: "用户通过审核,成为销售!",
  360. icon: 'none',
  361. });
  362. this.valueidbu=[]
  363. this.valueid=[]
  364. this.valueb=[]
  365. this.valuea=''
  366. this.valuej=''
  367. this.roleid=[]
  368. this.ids=''
  369. this.showcommpany=!this.showcommpany
  370. this.getUser()
  371. }else{
  372. uni.showToast({
  373. title: res.msg,
  374. icon: 'none',
  375. });
  376. }
  377. })
  378. },
  379. // 全选
  380. selectAll() {
  381. this.isSelectAll = !this.isSelectAll;
  382. this.selectedUsers = []; // 清空已选列表
  383. // 遍历所有用户项,更新 checked 状态
  384. this.list = this.list.map(group => {
  385. group.list = group.list.map(user => {
  386. if (this.isSelectAll) {
  387. this.selectedUsers.push(user.userId); // 添加用户ID到选中列表
  388. }
  389. return {
  390. ...user,
  391. checked: this.isSelectAll,
  392. };
  393. });
  394. return group;
  395. });
  396. // 如果取消全选,清空 selectedUsers
  397. if (!this.isSelectAll) {
  398. this.selectedUsers = [];
  399. }
  400. },
  401. // 单选 /反选
  402. changeitem(userId) {
  403. const index = this.selectedUsers.indexOf(userId);
  404. if (index === -1) {
  405. this.selectedUsers.push(userId); // 选中
  406. } else {
  407. this.selectedUsers.splice(index, 1); // 取消选中
  408. }
  409. // 更新全选状态
  410. this.isSelectAll = this.selectedUsers.length === this.getTotalUsers();
  411. },
  412. // 计算总用户数
  413. getTotalUsers() {
  414. return this.list.reduce((total, group) => total + group.list.length, 0);
  415. },
  416. tabact(index){
  417. this.list=[]
  418. this.act=index
  419. if(this.act==0){
  420. this.selectact=false
  421. this.isAudits=1
  422. this.getUser();
  423. }else if(this.act==1){
  424. this.isAudits=0
  425. this.getUser();
  426. }
  427. },
  428. getUser(){
  429. var data = {
  430. searchKey:this.searchContent,
  431. isAudit:this.isAudits
  432. };
  433. var that=this;
  434. getAllUsers(data).then(
  435. res => {
  436. if(res.code==200){
  437. that.list=res.users;
  438. this.list=this.list.map(group=>{
  439. group.list = group.list.map(user => {
  440. return {
  441. ...user,
  442. checked: this.isSelectAll,
  443. postname:user.post.map(item=>item.postName).join(","),
  444. rolesname:user.roles.map(item=>item.roleName).join(",")
  445. };
  446. })
  447. return group;
  448. })
  449. }
  450. },
  451. rej => {}
  452. );
  453. },
  454. //获取文字信息
  455. getCur(e) {
  456. this.hidden = false;
  457. this.listCur = this.list[e.target.id].firstLetter;
  458. },
  459. setCur(e) {
  460. this.hidden = true;
  461. this.listCur = this.listCur
  462. },
  463. //滑动选择Item
  464. tMove(e) {
  465. let y = e.touches[0].clientY,
  466. offsettop = this.boxTop,
  467. that = this;
  468. //判断选择区域,只有在选择区才会生效
  469. if (y > offsettop) {
  470. let num = parseInt((y - offsettop) / 20);
  471. console.log(num);
  472. if(num<that.list.length){
  473. this.listCur = that.list[num].firstLetter
  474. }
  475. };
  476. },
  477. //触发全部开始选择
  478. tStart() {
  479. this.hidden = false
  480. },
  481. //触发结束选择
  482. tEnd() {
  483. this.hidden = true;
  484. this.listCurID = this.listCur
  485. },
  486. indexSelect(e) {
  487. let that = this;
  488. let barHeight = this.barHeight;
  489. let list = this.list;
  490. let scrollY = Math.ceil(list.length * e.detail.y / barHeight);
  491. for (let i = 0; i < list.length; i++) {
  492. if (scrollY < i + 1) {
  493. that.listCur = list[i].firstLetter;
  494. that.movableY = i * 20
  495. return false
  496. }
  497. }
  498. },
  499. navTo(subitem){
  500. uni.navigateTo({
  501. url: './userInfo?userId='+subitem.userId
  502. })
  503. },
  504. search(){
  505. this.getUser()
  506. }
  507. }
  508. }
  509. </script>
  510. <style lang="scss">
  511. .quxiao{
  512. width: 40%;
  513. height: 70rpx;
  514. line-height: 70rpx;
  515. text-align: center;
  516. background-color: #F8F8FC;
  517. border: 2rpx solid #cacaca;
  518. color: #999;
  519. border-radius: 50rpx;
  520. }
  521. .queren{
  522. width: 40%;
  523. height: 70rpx;
  524. line-height: 70rpx;
  525. text-align: center;
  526. background-color: #1773ff;
  527. color: #fff;
  528. border-radius: 50rpx;
  529. }
  530. ::v-deep {
  531. .foot-select {
  532. position: fixed;
  533. bottom: 0;
  534. width: 100%;
  535. padding: 20rpx;
  536. background: #fff;
  537. box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.1);
  538. z-index: 1000;
  539. }
  540. }
  541. .active{
  542. color: #1773ff;
  543. font-weight: bold;
  544. }
  545. .notact{
  546. color: #888;
  547. }
  548. page {
  549. background-color: #F8F8FC;
  550. }
  551. .top{
  552. /* height: 88rpx; */
  553. background-color: #fff;
  554. padding: 0rpx 15rpx;
  555. padding-top: 20rpx;
  556. }
  557. .indexes {
  558. position: relative;
  559. }
  560. .indexBar {
  561. position: fixed;
  562. right: 0px;
  563. bottom: 0px;
  564. padding: 20upx 20upx 20upx 60upx;
  565. display: flex;
  566. align-items: center;
  567. }
  568. .indexBar .indexBar-box {
  569. width: 40upx;
  570. height: auto;
  571. background: #fff;
  572. display: flex;
  573. flex-direction: column;
  574. box-shadow: 0 0 20upx rgba(0, 0, 0, 0.1);
  575. border-radius: 10upx;
  576. }
  577. .indexBar-item {
  578. flex: 1;
  579. width: 40upx;
  580. height: 40upx;
  581. display: flex;
  582. align-items: center;
  583. justify-content: center;
  584. font-size: 24upx;
  585. color: #888;
  586. }
  587. movable-view.indexBar-item {
  588. width: 40upx;
  589. height: 40upx;
  590. z-index: 9;
  591. position: relative;
  592. }
  593. movable-view.indexBar-item::before {
  594. content: "";
  595. display: block;
  596. position: absolute;
  597. left: 0;
  598. top: 10upx;
  599. height: 20upx;
  600. width: 4upx;
  601. background-color: #f37b1d;
  602. }
  603. .indexToast {
  604. position: fixed;
  605. top: 0;
  606. right: 80upx;
  607. bottom: 0;
  608. background: rgba(0, 0, 0, 0.5);
  609. width: 100upx;
  610. height: 100upx;
  611. border-radius: 10upx;
  612. margin: auto;
  613. color: #fff;
  614. line-height: 100upx;
  615. text-align: center;
  616. font-size: 48upx;
  617. }
  618. .zm{
  619. height:30rpx;
  620. padding: 0rpx 20rpx;
  621. font-size: 24rpx;
  622. color: #888;
  623. background: #F8F8FC;
  624. }
  625. .user-list{
  626. margin: 20rpx;
  627. border-radius: 20rpx;
  628. }
  629. .user-item{
  630. width: 100%;
  631. margin: 12rpx 0;
  632. }
  633. .user-item .avatar{
  634. width: 100upx;
  635. height: 100upx;
  636. }
  637. .user-item .avatar .img{
  638. border-radius: 50%;
  639. width: 100%;
  640. height: 100%;
  641. }
  642. .user-item .content{
  643. margin-left: 15rpx;
  644. }
  645. .user-item .content .name{
  646. font-size: 26rpx;
  647. color: #111;
  648. }
  649. .user-item .content .dept{
  650. font-size: 24rpx;
  651. color: #888;
  652. margin-top: 15rpx;
  653. }
  654. </style>