Files
SmartParks_uniapp/pages/sys/workbench/book/book.vue
liyuanchao c7ff9a5234
Some checks failed
Uniapp 自动化打包 CI/CD / 打包 Uniapp 项目 (push) Has been cancelled
1.
2025-09-05 16:54:53 +08:00

213 lines
4.9 KiB
Vue

<template>
<view class="page">
<!-- 搜索框 -->
<view class="search-box">
<input type="text" class="search-input" placeholder="部门、岗位、姓名" v-model="keyword"/>
</view>
<!-- 联系人列表 -->
<scroll-view
scroll-y
class="contact-list"
:scroll-into-view="currentView"
scroll-with-animation
>
<block v-for="(group, gIndex) in contacts" :key="gIndex">
<view class="group-title" :id="'group-' + group.letter">{{ group.letter }}</view>
<view class="contact-item" v-for="(item, index) in group.list" :key="index">
<image class="avatar" :src="item.avatar"></image>
<view class="contact-info">
<text class="name" :class="{'highlight': item.isHighlight}">{{ item.name }}</text>
<text class="desc">{{ item.job }} {{ item.phone }}</text>
</view>
</view>
</block>
</scroll-view>
<!-- 字母索引栏 -->
<view
class="index-bar"
@touchstart="onTouch"
@touchmove.stop.prevent="onTouch"
@touchend="onTouchEnd"
@touchcancel="onTouchEnd"
>
<view
v-for="(letter, i) in indexList"
:key="i"
class="index-item"
:style="{height: indexItemHeight + 'rpx', lineHeight: indexItemHeight + 'rpx'}"
>
{{ letter }}
</view>
</view>
<!-- 居中大字母提示 -->
<view v-if="showLetter" class="letter-toast">
{{ showLetter }}
</view>
</view>
</template>
<script>
export default {
data() {
return {
keyword: "",
currentView: "",
showLetter: "",
indexList: "ABCDEFGHIJKLMNOPQRSTUVWXYZ#".split(""),
indexItemHeight: 30, // 索引单个高度 (rpx),可调整
contacts: [
{ letter: "A", list: [{ name: "张晓明", phone: "17895698899", job: "保洁", avatar: "https://img.yzcdn.cn/vant/cat.jpeg", isHighlight: true }] },
{ letter: "B", list: [
{ name: "阿俊", phone: "17895698899", job: "保洁", avatar: "https://img.yzcdn.cn/vant/dog.jpeg" },
{ name: "阿俊", phone: "17895698899", job: "保洁", avatar: "https://img.yzcdn.cn/vant/cat.jpeg" },
{ name: "阿俊", phone: "17895698899", job: "保洁", avatar: "https://img.yzcdn.cn/vant/elephant.jpeg" }
]},
{ letter: "C", list: [
{ name: "阿俊", phone: "17895698899", job: "保洁", avatar: "https://img.yzcdn.cn/vant/horse.jpeg" },
{ name: "阿俊", phone: "17895698899", job: "保洁", avatar: "https://img.yzcdn.cn/vant/lion.jpeg" }
]}
]
}
},
methods: {
// 开始/移动
onTouch(e) {
const touchY = e.touches[0].clientY
this.calcIndexByY(touchY)
},
// 松手/取消时隐藏
onTouchEnd() {
setTimeout(() => {
this.showLetter = ""
}, 300) // 0.3 秒后消失
},
// 计算位置 → 滚动 & 显示大字母
calcIndexByY(y) {
const query = uni.createSelectorQuery().in(this)
query.select('.index-bar').boundingClientRect(rect => {
if (!rect) return
const top = rect.top
const index = Math.floor((y - top) / (rect.height / this.indexList.length))
if (index >= 0 && index < this.indexList.length) {
const letter = this.indexList[index]
this.scrollTo(letter)
}
}).exec()
},
scrollTo(letter) {
const exists = this.contacts.find(item => item.letter === letter)
if (exists) {
this.currentView = "group-" + letter
}
this.showLetter = letter
}
}
}
</script>
<style>
.page {
display: flex;
flex-direction: column;
height: 100%;
background-color: #fff;
}
.header {
display: flex;
align-items: center;
height: 90rpx;
padding: 0 20rpx;
}
.back {
font-size: 40rpx;
}
.title {
flex: 1;
text-align: center;
font-size: 34rpx;
font-weight: bold;
}
.search-box {
padding: 20rpx;
}
.search-input {
width: auto;
height: 63rpx;
background: #F2F3F5;
border-radius: 25rpx;
padding-left: 20rpx;
font-size: 28rpx;
margin-left: 18rpx;
margin-right: 18rpx;
}
.contact-list {
flex: 1;
}
.group-title {
padding: 10rpx 20rpx;
background: #f5f5f5;
font-size: 26rpx;
color: #666;
}
.contact-item {
display: flex;
align-items: center;
padding: 20rpx;
border-bottom: 1px solid #f5f5f5;
}
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.contact-info {
display: flex;
flex-direction: column;
}
.name {
font-size: 30rpx;
}
.name.highlight {
color: orange;
}
.desc {
font-size: 24rpx;
color: #888;
margin-top: 6rpx;
}
.index-bar {
position: fixed;
right: 10rpx;
top: 200rpx;
display: flex;
flex-direction: column;
align-items: center;
background-color: transparent;
user-select: none;
}
.index-item {
font-size: 22rpx;
color: #3a6ea5;
}
.letter-toast {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.6);
color: #fff;
font-size: 80rpx;
font-weight: bold;
padding: 40rpx 60rpx;
border-radius: 20rpx;
}
</style>