personList.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <view class="page_person_list">
  3. <CommonHeader :title="headerTitle" @back="goBack"></CommonHeader>
  4. <SearchBar v-model="searchWord" @search="handleSearch" :isFixed="true" :top="searchBarTop + 'rpx'" :border="false"></SearchBar>
  5. <scroll-view scroll-y class="person_list" :style="{ paddingTop: contentPaddingTop + 'rpx' }">
  6. <view v-for="(person, index) in filteredList" :key="person.userId || person.id || index" class="person_item">
  7. <view class="person_info">
  8. <text class="person_name">{{ person.thirdName || person.name }}</text>
  9. <text class="person_code">({{ person.thirdCode || person.userAccount || '' }})</text>
  10. </view>
  11. <view class="person_action" @click="openDeleteModal(index)">
  12. <text class="delete_text">删除</text>
  13. </view>
  14. </view>
  15. <view v-if="filteredList.length === 0" class="empty_state">
  16. <text class="empty_text">暂无人员</text>
  17. </view>
  18. </scroll-view>
  19. <ConfirmModal
  20. :visible="showDeleteModal"
  21. title="提示"
  22. :content="`确定要删除【${deletePersonName}】吗?`"
  23. cancelText="取消"
  24. confirmText="确定"
  25. @cancel="closeDeleteModal"
  26. @confirm="confirmDelete"
  27. ></ConfirmModal>
  28. </view>
  29. </template>
  30. <script setup>
  31. import { ref, computed, onMounted } from 'vue';
  32. import CommonHeader from '@/components/commonHeader.vue';
  33. import SearchBar from '@/components/searchBar.vue';
  34. import ConfirmModal from '@/components/confirmModal.vue';
  35. import { useSafeArea } from '@/common/safeArea';
  36. const { statusBarHeight, initSafeArea } = useSafeArea();
  37. const HEADER_CONTENT_HEIGHT = 174;
  38. const SEARCHBAR_HEIGHT = 60;
  39. const SPACING = 24;
  40. const searchBarTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT);
  41. const contentPaddingTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT + SEARCHBAR_HEIGHT + SPACING);
  42. const searchWord = ref('');
  43. const personList = ref([]);
  44. const objectTypeLabel = ref('');
  45. const showDeleteModal = ref(false);
  46. const deleteIndex = ref(-1);
  47. const deletePersonName = ref('');
  48. const filteredList = computed(() => {
  49. if (!searchWord.value) return personList.value;
  50. const keyword = searchWord.value.toLowerCase();
  51. return personList.value.filter(person => {
  52. const name = (person.thirdName || person.name || '').toLowerCase();
  53. const code = (person.thirdCode || person.userAccount || '').toLowerCase();
  54. return name.includes(keyword) || code.includes(keyword);
  55. });
  56. });
  57. const headerTitle = computed(() => {
  58. return `${objectTypeLabel.value || ''} 已选${personList.value.length}人`;
  59. });
  60. const handleSearch = (keyword) => {
  61. searchWord.value = keyword;
  62. };
  63. const openDeleteModal = (index) => {
  64. const person = personList.value[index];
  65. deletePersonName.value = person.thirdName || person.name || '';
  66. deleteIndex.value = index;
  67. showDeleteModal.value = true;
  68. };
  69. const closeDeleteModal = () => {
  70. showDeleteModal.value = false;
  71. deleteIndex.value = -1;
  72. deletePersonName.value = '';
  73. };
  74. const confirmDelete = () => {
  75. if (deleteIndex.value >= 0) {
  76. personList.value.splice(deleteIndex.value, 1);
  77. }
  78. closeDeleteModal();
  79. };
  80. const goBack = () => {
  81. uni.setStorageSync('personListResult', JSON.stringify({
  82. users: personList.value
  83. }));
  84. uni.navigateBack();
  85. };
  86. onMounted(() => {
  87. initSafeArea();
  88. const data = uni.getStorageSync('personListData');
  89. if (data) {
  90. try {
  91. const parsed = JSON.parse(data);
  92. // 不去重,直接使用所有用户
  93. personList.value = parsed.users || [];
  94. objectTypeLabel.value = parsed.tab || '';
  95. } catch (e) {
  96. console.error('解析人员列表数据失败:', e);
  97. }
  98. }
  99. });
  100. </script>
  101. <style lang="scss">
  102. .page_person_list {
  103. display: flex;
  104. flex-direction: column;
  105. min-height: 100vh;
  106. }
  107. .person_list {
  108. flex: 1;
  109. padding-left: 24rpx;
  110. padding-right: 24rpx;
  111. padding-bottom: 24rpx;
  112. box-sizing: border-box;
  113. }
  114. .person_item {
  115. display: flex;
  116. align-items: center;
  117. justify-content: space-between;
  118. height: 86rpx;
  119. border-bottom: 2rpx solid #F3F3F3;
  120. .person_info {
  121. display: flex;
  122. align-items: center;
  123. .person_name {
  124. font-size: 28rpx;
  125. color: #666;
  126. }
  127. .person_code {
  128. font-size: 28rpx;
  129. color: #666;
  130. margin-left: 16rpx;
  131. }
  132. }
  133. .person_action {
  134. .delete_text {
  135. font-size: 28rpx;
  136. color: #F56C6C;
  137. }
  138. }
  139. }
  140. .empty_state {
  141. display: flex;
  142. flex-direction: column;
  143. align-items: center;
  144. padding: 100rpx 0;
  145. .empty_text {
  146. font-size: 28rpx;
  147. color: #999999;
  148. }
  149. }
  150. </style>