index.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <template>
  2. <view class="contacts-v">
  3. <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :sticky="true"
  4. :down="downOption" :up="upOption" :bottombar="false">
  5. <view class="search-box search-box_sticky">
  6. <u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
  7. :show-action="false" @change="search" bg-color="#f0f2f6" shape="square">
  8. </u-search>
  9. <view class="organization u-border-bottom">{{keyword?'联系人':'组织列表'}}</view>
  10. </view>
  11. <view class="list-cell u-p-l-20 u-p-r-20" v-if="!keyword">
  12. <scroll-view :scroll-y="true" style="height: 100%">
  13. <ly-tree :tree-data="list" :node-key="defaultProps.value" :props="defaultProps"
  14. :load="loadNode" lazy :default-expand-all='false' :show-node-icon="true"
  15. :defaultExpandedKeys="defaultExpandedKeys" child-visible-for-filter-node
  16. @node-click="handleNodeClick" ref="tree">
  17. </ly-tree>
  18. </scroll-view>
  19. </view>
  20. <view class="list-cell u-p-l-20 u-p-r-20" v-for="(item, i) in list" :key="i" @click="detail(item)" v-else>
  21. <view class="u-border-bottom list-item u-font-28 u-flex" v-if="list.length">
  22. <u-avatar :src="baseURL+item.headIcon"></u-avatar>
  23. <view class="list-cell-txt">
  24. <view class="u-font-30 u-m-b-4" style="color: #303133;font-size: 28rpx;">
  25. {{item.realName}}/{{item.account}}
  26. </view>
  27. <view class="u-font-24 department u-m-t-4">{{item.department}}</view>
  28. </view>
  29. </view>
  30. </view>
  31. </mescroll-body>
  32. </view>
  33. </template>
  34. <script>
  35. import {
  36. getOrgAndPosSelector
  37. } from '@/api/message.js'
  38. import {
  39. getUserList
  40. } from '@/api/common.js'
  41. import resources from '@/libs/resources.js'
  42. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  43. export default {
  44. mixins: [MescrollMixin],
  45. data() {
  46. return {
  47. downOption: {
  48. use: true,
  49. auto: true
  50. },
  51. upOption: {
  52. page: {
  53. num: 0,
  54. size: 20,
  55. time: null
  56. },
  57. empty: {
  58. use: true,
  59. icon: resources.message.nodata,
  60. tip: this.$t('common.noData'),
  61. fixed: true,
  62. top: "300rpx",
  63. },
  64. textNoMore: this.$t('app.apply.noMoreData'),
  65. },
  66. keyword: '',
  67. list: [],
  68. defaultProps: {
  69. label: 'fullName',
  70. value: 'id',
  71. icon: 'icon',
  72. children: 'children',
  73. isLeaf: 'isLeaf'
  74. },
  75. level: 0,
  76. }
  77. },
  78. computed: {
  79. baseURL() {
  80. return this.define.baseURL
  81. },
  82. defaultExpandedKeys() {
  83. return this.list.length ? [this.list[0].id] : []
  84. }
  85. },
  86. methods: {
  87. upCallback(page) {
  88. let query = this.keyword ? {
  89. currentPage: page.num,
  90. pageSize: page.size,
  91. keyword: this.keyword,
  92. organizeId: '',
  93. organizeName: '',
  94. positionId: ''
  95. } : {
  96. id: '0',
  97. type: 'organize'
  98. };
  99. let method = this.keyword ? getUserList(query) : getOrgAndPosSelector(query);
  100. method.then(res => {
  101. const list = res.data.list || [];
  102. if (!this.keyword) {
  103. this.list = list;
  104. return this.mescroll.endSuccess(true);
  105. }
  106. this.mescroll.endSuccess(list.length);
  107. if (page.num === 1) this.list = [];
  108. this.list = this.list.concat(list);
  109. }).catch(() => {
  110. this.mescroll.endErr();
  111. });
  112. },
  113. loadNode(node, resolve) {
  114. let query = {
  115. id: node.key || 0,
  116. type: node.data.type || 'organize'
  117. }
  118. getOrgAndPosSelector(query).then(res => {
  119. resolve(res.data.list)
  120. })
  121. },
  122. search() {
  123. // 节流,避免输入过快多次请求
  124. this.searchTimer && clearTimeout(this.searchTimer)
  125. this.searchTimer = setTimeout(() => {
  126. this.list = [];
  127. this.mescroll.resetUpScroll();
  128. }, 300)
  129. },
  130. handleNodeClick(data) {
  131. const type = data.data.type
  132. const config = {
  133. organizeId: type === 'organize' ? data.key : data.data?.organizeId,
  134. organizeName: data.label,
  135. ...(type === 'position' ? {
  136. positionId: data.key
  137. } : {})
  138. };
  139. uni.navigateTo({
  140. url: '/pages/my/contacts/userList?config=' + encodeURIComponent(JSON.stringify(
  141. config)),
  142. })
  143. },
  144. detail(item) {
  145. uni.navigateTo({
  146. url: '/pages/my/userDetail/index?data=' + encodeURIComponent(JSON.stringify(
  147. item))
  148. })
  149. },
  150. }
  151. }
  152. </script>
  153. <style lang="scss">
  154. page {
  155. background-color: #eef0f4;
  156. }
  157. .contacts-v {
  158. ::v-deep .ly-tree-node__icon {
  159. width: 1.5rem;
  160. height: 1.5rem;
  161. overflow: hidden;
  162. margin-right: 0.5rem;
  163. background: #43a1f3;
  164. border-radius: 50%;
  165. text-align: center;
  166. line-height: 1.5rem;
  167. color: #fff;
  168. font-size: 24rpx;
  169. }
  170. .organization {
  171. width: 100%;
  172. background-color: #fff;
  173. padding: 20rpx;
  174. font-size: 32rpx;
  175. }
  176. .list-cell {
  177. width: 100%;
  178. background-color: #fff;
  179. .list-item {
  180. box-sizing: border-box;
  181. overflow: hidden;
  182. color: $u-content-color;
  183. height: 136rpx;
  184. .list-cell-txt {
  185. margin-left: 20rpx;
  186. .department {
  187. color: #909399;
  188. font-size: 24rpx;
  189. }
  190. }
  191. }
  192. }
  193. }
  194. </style>