UserListVue.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <uni-list style="width: 100%">
  3. <view v-for="(groupedUser) in groupedUsers" :key="groupedUser.category">
  4. <div ref="contactItem" class="contact-item">
  5. <div v-if="showCategoryLabel" class="label"
  6. :style="paddingStyle"
  7. v-bind:class="{sticky:enableCategoryLabelSticky}">
  8. <p>{{ groupedUser.category.toUpperCase() }}</p>
  9. </div>
  10. <uni-list style="width: 100%">
  11. <view v-for="(user) in groupedUser.users" :key="user.uid">
  12. <div class="content"
  13. :name="'user-'+user.uid"
  14. :style="paddingStyle"
  15. v-bind:class="{active: (sharedContactState.currentFriend
  16. && user._category === sharedContactState.currentFriend._category
  17. && user.uid === sharedContactState.currentFriend.uid) || (currentUser && currentUser.uid === user.uid)}"
  18. @click.stop="clickUserItem(user)">
  19. <img class="avatar" :src="user.portrait" alt="" @error="imgUrlAlt">
  20. <div style="padding-left: 10px">
  21. <p class="single-line"> {{ user._displayName ? user._displayName : user.displayName }}</p>
  22. <p v-if="user._userOnlineStatusDesc" class="single-line user-online-status"> {{ user._userOnlineStatusDesc }}</p>
  23. </div>
  24. </div>
  25. </view>
  26. </uni-list>
  27. </div>
  28. </view>
  29. </uni-list>
  30. </template>
  31. <script>
  32. import store from "../../store";
  33. import UserCardView from "./UserCardView";
  34. import Config from "../../config";
  35. import UniList from "../../components/uni-list/uni-list.vue";
  36. export default {
  37. name: "UserListVue",
  38. props: {
  39. users: {
  40. type: Array,
  41. required: true,
  42. },
  43. currentUser: {
  44. type: Object,
  45. default: null,
  46. },
  47. showCategoryLabel: {
  48. type: Boolean,
  49. required: false,
  50. default: true,
  51. },
  52. enableCategoryLabelSticky: {
  53. type: Boolean,
  54. required: false,
  55. default: false,
  56. },
  57. clickUserItemFunc: {
  58. type: Function,
  59. required: false,
  60. },
  61. paddingLeft: {
  62. type: String,
  63. required: false,
  64. default: '5px'
  65. }
  66. },
  67. data() {
  68. return {
  69. sharedContactState: store.state.contact,
  70. }
  71. },
  72. methods: {
  73. clickUserItem(user) {
  74. if (this.clickUserItemFunc) {
  75. this.clickUserItemFunc(user);
  76. } else {
  77. store.setCurrentFriend(user)
  78. uni.navigateTo({
  79. url: '/pages/contact/UserDetailPage',
  80. success: () => {
  81. console.log('nav to UserDetailPage success');
  82. },
  83. fail: (err) => {
  84. console.log('nav to UserDetailPage err', err);
  85. }
  86. });
  87. }
  88. },
  89. scrollActiveElementCenter() {
  90. let el = this.$el.getElementsByClassName("active")[0];
  91. el && el.scrollIntoView({behavior: "instant", block: "center"});
  92. },
  93. imgUrlAlt(e) {
  94. e.target.src = Config.DEFAULT_PORTRAIT_URL;
  95. }
  96. },
  97. mounted() {
  98. console.log('userList', this.users.length);
  99. },
  100. activated() {
  101. this.scrollActiveElementCenter();
  102. },
  103. destroyed() {
  104. },
  105. computed: {
  106. groupedUsers() {
  107. let groupedUsers = [];
  108. if (!this.showCategoryLabel) {
  109. groupedUsers.push({
  110. category: 'not-show-category',
  111. users: this.users,
  112. })
  113. } else {
  114. let current = {};
  115. let lastCategory = null;
  116. this.users.forEach((user) => {
  117. if (!lastCategory || lastCategory !== user._category) {
  118. lastCategory = user._category;
  119. current = {
  120. category: user._category,
  121. users: [user],
  122. };
  123. groupedUsers.push(current);
  124. } else {
  125. current.users.push(user);
  126. }
  127. });
  128. }
  129. return groupedUsers;
  130. },
  131. paddingStyle() {
  132. return {
  133. paddingLeft: this.paddingLeft
  134. }
  135. },
  136. },
  137. components: {
  138. UniList,
  139. UserCardView,
  140. },
  141. }
  142. </script>
  143. <style lang="css" scoped>
  144. .contact-item {
  145. --user-item-padding-left: 30px;
  146. }
  147. ul {
  148. list-style: none;
  149. width: 100%;
  150. }
  151. .avatar {
  152. width: 40px;
  153. height: 40px;
  154. border-radius: 3px;
  155. }
  156. .checkbox {
  157. margin-right: 10px;
  158. }
  159. .contact-item {
  160. display: flex;
  161. flex-direction: column;
  162. font-size: 13px;
  163. align-items: flex-start;
  164. }
  165. .contact-item .label {
  166. width: 100%;
  167. background-color: #fafafa;
  168. }
  169. .contact-item .label p {
  170. padding: 5px 5px 5px 0;
  171. border-bottom: 1px solid #e0e0e0;
  172. }
  173. .contact-item .label.sticky {
  174. position: sticky;
  175. top: 0;
  176. }
  177. .contact-item .content {
  178. padding: 5px 5px 5px 0;
  179. display: flex;
  180. width: 100%;
  181. align-items: center;
  182. }
  183. .contact-item .content span {
  184. margin-left: 10px;
  185. }
  186. .contact-item .content.active {
  187. background-color: #d6d6d6;
  188. }
  189. .contact-item .content:active {
  190. background-color: #d6d6d6;
  191. }
  192. .user-online-status {
  193. color: gray;
  194. font-size: 10px;
  195. }
  196. /*.contact-item .content:hover {*/
  197. /* background-color: red;*/
  198. /*}*/
  199. </style>