吉安感知网项目-前端
shuishen
2026-02-03 89380e6260a75d1d3b94de687ebcc2f50d50659d
uniapps/work-app/src/pages/voiceCall/index.vue
@@ -2,92 +2,142 @@
  <div class="voiceCallContainer" :style="{ paddingTop: topMargin + 'px' }">
    <!-- 顶部搜索栏 -->
    <div class="searchBar">
      <up-search placeholder="请输入关键字搜索"  :animation="true"   :show-action="false"></up-search>
      <up-search placeholder="请输入关键字搜索" v-model="defaultParam.friendNickName"  :animation="true"   :show-action="false" @confirm="onSearch"  @search="onSearch" @clear="handleClear"></up-search>
    </div>
    <!-- 联系人列表 -->
   <div class="contactList">
     <div
       class="contactItem"
       v-for="(contact, index) in filteredContacts"
       :key="index"
     >
  <div class="itemBox">
    <!-- 头像 -->
    <div class="contactAvatar">
      <image :src="contact.avatar" mode="aspectFill" />
    </div>
    <div class="contactList" @scrolltolower="onScrollToLower">
      <div
        class="contactItem"
        v-for="(contact, index) in contacts"
        :key="index"
      >
        <div class="itemBox">
          <!-- 头像 -->
          <div class="contactAvatar">
            <image :src="contact.avatar || defaultAvatar"  />
          </div>
    <!-- 联系人信息 -->
    <div class="contactInfo">
      <div class="contactName">{{ contact.name }}</div>
      <div class="contactDept">{{ contact.dept }}</div>
    </div>
          <!-- 联系人信息 -->
          <div class="contactInfo">
            <div class="contactName">{{ contact.friendNickName  || '未知联系人' }}</div>
            <div class="contactDept">{{ contact.deptName || '未知部门' }}</div>
          </div>
    <!-- 电话按钮 -->
    <div class="callButton" @click="makeCall(contact)">
      <image src="@/static/images/voiceVal/phoneVal.svg" mode="aspectFit" />
    </div>
  </div>
          <!-- 电话按钮 -->
          <div class="callButton" @click="makeCall(contact)">
            <image src="@/static/images/voiceVal/phoneVal.svg"  />
          </div>
        </div>
     </div>
   </div>
      </div>
      <!-- 加载提示 -->
      <div class="loadingMore">
        <text v-if="loading">加载中...</text>
      </div>
    </div>
  </div>
</template>
<script setup>
import { getStatusBarHeight } from '@/utils/common';
const topMargin = getStatusBarHeight()
// 搜索关键字
const searchKeyword = ref('')
import { getPhoneBookListApi } from '@/api/voiceCall/index.js'
import { onShow } from '@dcloudio/uni-app'
import defaultAvatar from '/static/images/defaultAvatar.svg'
// 联系人数据
const contacts = ref([
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
  { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' },
])
// 过滤后的联系人列表
const filteredContacts = computed(() => {
  if (!searchKeyword.value) {
    return contacts.value
  }
  return contacts.value.filter(contact => {
    return contact.name.includes(searchKeyword.value) ||
      contact.dept.includes(searchKeyword.value)
  })
const contacts = ref([])
const defaultParam = ref({
  current: 1,
  size: 10,
  friendNickName: ''
})
// 加载状态
const loading = ref(false)
const hasMore = ref(true)
// 获取通讯录
const getPhoneBookList = () => {
  if (loading.value || !hasMore.value) return
  loading.value = true
  // 添加分页参数
  const params = {
    current: defaultParam.value.current,
    size: defaultParam.value.size,
    friendNickName: defaultParam.value.friendNickName
  }
  getPhoneBookListApi(params).then(res => {
    const response = res.data.data
    if (defaultParam.value.current === 1) {
      contacts.value = response.records
    } else {
      contacts.value = [...contacts.value, ...response.records]
    }
    // 判断是否还有更多数据
    if (response.records.length < defaultParam.value.size || response.current >= response.pages) {
      hasMore.value = false
    } else {
      hasMore.value = true
    }
  }).catch(err => {
    console.error('获取通讯录失败:', err)
    const errorMsg = err.msg || err.message || '获取通讯录失败'
    uni.showToast({
      title: errorMsg,
      icon: 'none',
      duration: 3000
    })
  }).finally(() => {
    loading.value = false
  })
}
// 加载更多
const loadMore = () => {
  if (loading.value || !hasMore.value) return
  defaultParam.value.current++
  getPhoneBookList()
}
const onSearch = () => {
  defaultParam.value.current = 1
  hasMore.value = true
  getPhoneBookList()
}
const handleClear = () => {
  defaultParam.value.friendNickName = ''
  defaultParam.value.current = 1
  hasMore.value = true
  getPhoneBookList()
}
// 拨打电话方法
const makeCall = (contact) => {
  console.log('拨打电话给', contact.name)
  // 这里可以添加实际的拨打电话逻辑
  uni.showToast({
    title: `正在拨打${contact.name}的电话`,
    icon: 'none'
  console.log('拨打电话', contact)
  // 将contact对象转换为JSON字符串并URL编码
  const contactStr = encodeURIComponent(JSON.stringify(contact))
  uni.navigateTo({
    url: `/subPackages/voiceCallDetail/index?contact=${contactStr}`,
  })
}
onShow(() => {
  // 重置分页参数
  defaultParam.value.current = 1
  hasMore.value = true
  getPhoneBookList()
});
// 监听滚动到底部
const onScrollToLower = () => {
  loadMore()
}
</script>
@@ -101,16 +151,24 @@
}
.searchBar {
  padding: 20rpx;
  padding: 20rpx 20rpx 0 20rpx;
  display: flex;
  align-items: center;
  height: 108rpx;
  :deep(){
    .u-search__content{
      background: #fff !important;
    }
    .u-search__content__input{
      background: #fff !important;
    }
  }
}
.contactList {
  margin: 0 24rpx;
  margin: 0 20rpx 20rpx 20rpx;
  background: #fff;
  border-radius: 12rpx ;
  border-radius: 12rpx;
  overflow-y: auto;
  height: 0;
  flex-grow: 1;
@@ -120,17 +178,19 @@
.contactItem {
  display: flex;
  align-items: center;
  padding:0 24rpx;
  padding: 0 20rpx;
}
.itemBox {
  display: flex;
 align-items: center;
  align-items: center;
  justify-content: space-between;
  width:100%;
  width: 100%;
  height: 98rpx;
  border-bottom: 1rpx solid #EBEBEB;
}
.contactAvatar {
  width: 80rpx;
  height: 80rpx;
@@ -180,4 +240,13 @@
  height: 60rpx;
}
.loadingMore {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 80rpx;
  font-size: 28rpx;
  color: #999;
}
</style>