list-user.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <view class="personnel-list" v-if="data && data.length">
  3. <view class="personnel-item" v-for="(item, index) of data" :key="item.id || index" @click="handleItemClick(item, index)">
  4. <view class="personnel-img">
  5. <UserAvatar :userName="item.nickName || item.userName" :avatarLink="item.avatar" />
  6. </view>
  7. <view class="personnel-name">{{ item.nickName || item.userName }}</view>
  8. <view v-if="showDelete" class="delete-icon" @click.stop="handleDelete(index)">
  9. <uni-icons type="close" size="16" color="#999"></uni-icons>
  10. </view>
  11. </view>
  12. </view>
  13. </template>
  14. <script>
  15. import UserAvatar from '@/pages/attendance/components/UserAvatar.vue'
  16. export default {
  17. name: 'ListUser',
  18. components: {
  19. UserAvatar
  20. },
  21. props: {
  22. // 人员数据数组
  23. data: {
  24. type: Array,
  25. default: () => []
  26. },
  27. // 是否显示删除图标
  28. showDelete: {
  29. type: Boolean,
  30. default: false
  31. },
  32. // 禁用状态
  33. disabled: {
  34. type: Boolean,
  35. default: false
  36. }
  37. },
  38. methods: {
  39. // 处理删除操作
  40. handleDelete(index) {
  41. if (!this.data || !this.data.length || this.disabled) return
  42. // 创建新数组(避免直接修改props)
  43. const newData = [...this.data]
  44. const deletedItem = newData.splice(index, 1)[0]
  45. // 向外传递删除后的数组和删除的项
  46. this.$emit('update:data', newData)
  47. this.$emit('delete', {
  48. deletedItem,
  49. index,
  50. newData
  51. })
  52. uni.showToast({
  53. title: '删除成功',
  54. icon: 'success',
  55. duration: 1500
  56. })
  57. },
  58. // 处理人员项点击
  59. handleItemClick(item, index) {
  60. this.$emit('click', {
  61. clickedItem: item,
  62. index,
  63. data: this.data
  64. })
  65. }
  66. }
  67. }
  68. </script>
  69. <style lang="scss" scoped>
  70. .personnel-list {
  71. display: flex;
  72. flex-wrap: wrap;
  73. gap: 16rpx;
  74. margin: 20rpx 0;
  75. }
  76. .personnel-item {
  77. display: flex;
  78. align-items: center;
  79. background: #f8f9fa;
  80. border-radius: 24rpx;
  81. padding: 12rpx 20rpx;
  82. position: relative;
  83. .personnel-img {
  84. width: 60rpx;
  85. height: 60rpx;
  86. border-radius: 50%;
  87. overflow: hidden;
  88. margin-right: 16rpx;
  89. flex-shrink: 0;
  90. }
  91. .personnel-name {
  92. font-size: 28rpx;
  93. color: #333;
  94. font-weight: 500;
  95. flex: 1;
  96. min-width: 0;
  97. overflow: hidden;
  98. text-overflow: ellipsis;
  99. white-space: nowrap;
  100. }
  101. .delete-icon {
  102. width: 40rpx;
  103. height: 40rpx;
  104. border-radius: 50%;
  105. background: #f0f0f0;
  106. display: flex;
  107. align-items: center;
  108. justify-content: center;
  109. margin-left: 16rpx;
  110. flex-shrink: 0;
  111. cursor: pointer;
  112. transition: background-color 0.2s;
  113. &:hover {
  114. background: #e0e0e0;
  115. }
  116. &:active {
  117. background: #d0d0d0;
  118. }
  119. }
  120. }
  121. </style>