303 lines
7.9 KiB
Vue
303 lines
7.9 KiB
Vue
|
|
<!-- 物业日常 - 打卡记录页面 -->
|
|||
|
|
<template>
|
|||
|
|
<s-layout title="物业日常" :bgStyle="{ backgroundColor:'#F8EDE8' }" navbar="inner" color="#333333">
|
|||
|
|
<view class="daily-page">
|
|||
|
|
<!-- 渐变背景装饰 -->
|
|||
|
|
<view class="gradient-bg"></view>
|
|||
|
|
|
|||
|
|
<!-- 固定头部区域:搜索栏 -->
|
|||
|
|
<view class="page-header">
|
|||
|
|
<view class="search-wrapper">
|
|||
|
|
<view class="search-box">
|
|||
|
|
<image class="search-icon" src="/static/img/guest.png" mode="aspectFit" />
|
|||
|
|
<input class="search-input" type="text" placeholder="搜索" placeholder-class="search-placeholder" />
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 网格内容区 - 独立滚动 -->
|
|||
|
|
<scroll-view scroll-y class="content-scroll" :style="{ height: scrollHeight + 'px' }" @scrolltolower="loadMore">
|
|||
|
|
<view class="grid-container">
|
|||
|
|
<view
|
|||
|
|
v-for="(item, index) in dataList"
|
|||
|
|
:key="item.id"
|
|||
|
|
class="card-item"
|
|||
|
|
@tap="handleCardTap(item)"
|
|||
|
|
>
|
|||
|
|
<!-- 图片区域 + 底部水印遮罩 -->
|
|||
|
|
<view class="card-img-wrap">
|
|||
|
|
<image class="card-img" :src="item.image" mode="aspectFill" />
|
|||
|
|
<!-- 底部渐变遮罩 + 打卡信息 -->
|
|||
|
|
<view class="card-overlay">
|
|||
|
|
<view class="overlay-info">
|
|||
|
|
<!-- 第一行:打卡人姓名 + 时间 -->
|
|||
|
|
<view class="info-row row-name">
|
|||
|
|
<image class="row-icon" src="/static/img/login_img.png" mode="aspectFill" />
|
|||
|
|
<text class="info-name">{{ item.userName }}</text>
|
|||
|
|
<text class="info-time">{{ item.time }}</text>
|
|||
|
|
</view>
|
|||
|
|
<!-- 第二行:打卡地点 -->
|
|||
|
|
<view class="info-row row-addr">
|
|||
|
|
<image class="row-icon" src="/static/img/guest.png" mode="aspectFit" />
|
|||
|
|
<text class="info-addr">{{ item.address }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
|
|||
|
|
<!-- 右下角悬浮相机按钮 - 仅物业人员可见 -->
|
|||
|
|
<view v-if="isStaff" class="fab-camera" @tap="handleCameraTap">
|
|||
|
|
<image class="camera-img" src="/static/img/login_img.png" mode="aspectFit" />
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</s-layout>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
|||
|
|
|
|||
|
|
// ==================== 数据定义 ====================
|
|||
|
|
|
|||
|
|
// scroll-view 滚动高度(单位 px)
|
|||
|
|
const scrollHeight = ref(0);
|
|||
|
|
|
|||
|
|
// 当前登录用户身份(true=物业人员,false=普通业主)
|
|||
|
|
const isStaff = ref(true);
|
|||
|
|
|
|||
|
|
// 模拟打卡数据列表(来自绑定小区的物业人员打卡记录)
|
|||
|
|
const dataList = ref([
|
|||
|
|
{ id: 1, image: 'https://picsum.photos/400/500?random=1', userName: '吴仁贵', time: '2026/01/08 14:52', address: '融侨馨苑12号楼' },
|
|||
|
|
{ id: 2, image: 'https://picsum.photos/400/480?random=2', userName: '张伟', time: '2026/01/08 15:20', address: '融侨馨苑3号楼' },
|
|||
|
|
{ id: 3, image: 'https://picsum.photos/400/520?random=3', userName: '李明', time: '2026/01/08 16:05', address: '融侨馨苑8号楼' },
|
|||
|
|
{ id: 4, image: 'https://picsum.photos/400/490?random=4', userName: '王芳', time: '2026/01/09 09:10', address: '融侨馨苑5号楼' },
|
|||
|
|
{ id: 5, image: 'https://picsum.photos/400/510?random=5', userName: '赵强', time: '2026/01/09 11:30', address: '融侨馨苑11号楼' },
|
|||
|
|
{ id: 6, image: 'https://picsum.photos/400/500?random=6', userName: '吴仁贵', time: '2026/01/09 14:00', address: '融侨馨苑12号楼' }
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
// ==================== 生命周期 ====================
|
|||
|
|
|
|||
|
|
onMounted(() => {
|
|||
|
|
calcScrollHeight();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// ==================== 方法 ====================
|
|||
|
|
|
|||
|
|
/** 动态计算 scroll-view 高度 */
|
|||
|
|
function calcScrollHeight() {
|
|||
|
|
const instance = getCurrentInstance();
|
|||
|
|
nextTick(() => {
|
|||
|
|
const sysInfo = uni.getSystemInfoSync();
|
|||
|
|
uni.createSelectorQuery()
|
|||
|
|
.in(instance)
|
|||
|
|
.select('.page-header')
|
|||
|
|
.boundingClientRect((rect) => {
|
|||
|
|
if (rect) {
|
|||
|
|
scrollHeight.value = sysInfo.windowHeight - rect.height - rect.top;
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.exec();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 点击卡片 - 查看详情 */
|
|||
|
|
function handleCardTap(item) {
|
|||
|
|
console.log('查看打卡详情:', item);
|
|||
|
|
uni.showToast({ title: `查看${item.userName}的打卡记录`, icon: 'none' });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 物业人员拍照打卡 */
|
|||
|
|
function handleCameraTap() {
|
|||
|
|
// 调起相机拍照
|
|||
|
|
uni.chooseImage({
|
|||
|
|
count: 1,
|
|||
|
|
sourceType: ['camera'],
|
|||
|
|
success: (res) => {
|
|||
|
|
const tempPath = res.tempFilePaths[0];
|
|||
|
|
// TODO: 上传图片并创建打卡记录(含水印:姓名、时间、地址)
|
|||
|
|
uni.showLoading({ title: '上传中...' });
|
|||
|
|
setTimeout(() => {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
uni.showToast({ title: '打卡成功', icon: 'success' });
|
|||
|
|
// 刷新列表(实际项目中重新请求接口)
|
|||
|
|
}, 1500);
|
|||
|
|
},
|
|||
|
|
fail: () => {
|
|||
|
|
// 用户取消拍照,不做处理
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 加载更多 */
|
|||
|
|
function loadMore() {
|
|||
|
|
console.log('加载更多打卡记录');
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
/* 页面容器 */
|
|||
|
|
.daily-page {
|
|||
|
|
position: relative;
|
|||
|
|
min-height: 100vh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 渐变背景 */
|
|||
|
|
.gradient-bg {
|
|||
|
|
position: absolute;
|
|||
|
|
top: -176rpx;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
height: calc(100% + 176rpx);
|
|||
|
|
background: linear-gradient(180deg, #F8EDE8 0%, #FFFFFF 30%);
|
|||
|
|
z-index: -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 固定头部(搜索栏) */
|
|||
|
|
.page-header {
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 搜索栏 */
|
|||
|
|
.search-wrapper {
|
|||
|
|
padding: 24rpx 32rpx;
|
|||
|
|
|
|||
|
|
.search-box {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
height: 72rpx;
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
border-radius: 36rpx;
|
|||
|
|
padding: 0 28rpx;
|
|||
|
|
|
|||
|
|
.search-icon {
|
|||
|
|
width: 32rpx;
|
|||
|
|
height: 32rpx;
|
|||
|
|
margin-right: 16rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.search-input {
|
|||
|
|
flex: 1;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.search-placeholder) {
|
|||
|
|
color: #999999;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 列表滚动区域 */
|
|||
|
|
.content-scroll {
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 双列网格容器 */
|
|||
|
|
.grid-container {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(2, 1fr);
|
|||
|
|
gap: 20rpx;
|
|||
|
|
padding: 0 24rpx 160rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 卡片 */
|
|||
|
|
.card-item {
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
border-radius: 20rpx;
|
|||
|
|
overflow: hidden;
|
|||
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
|
|||
|
|
|
|||
|
|
/* 图片容器 */
|
|||
|
|
.card-img-wrap {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 420rpx;
|
|||
|
|
position: relative;
|
|||
|
|
|
|||
|
|
.card-img {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
display: block;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 底部渐变遮罩层 */
|
|||
|
|
.card-overlay {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
bottom: 0;
|
|||
|
|
padding: 20rpx 16rpx 14rpx;
|
|||
|
|
background: linear-gradient(to top, rgba(0, 0, 0, 0.65) 0%, transparent 100%);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 遮罩内信息区 */
|
|||
|
|
.overlay-info {
|
|||
|
|
.info-row {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
|
|||
|
|
&:not(:last-child) {
|
|||
|
|
margin-bottom: 8rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.row-icon {
|
|||
|
|
width: 24rpx;
|
|||
|
|
height: 24rpx;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
margin-right: 8rpx;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 第一行:姓名 + 时间 */
|
|||
|
|
.row-name {
|
|||
|
|
.info-name {
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
font-weight: 500;
|
|||
|
|
color: #FFFFFF;
|
|||
|
|
margin-right: 12rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-time {
|
|||
|
|
font-size: 20rpx;
|
|||
|
|
color: rgba(255, 255, 255, 0.7);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 第二行:地址 */
|
|||
|
|
.row-addr {
|
|||
|
|
.info-addr {
|
|||
|
|
font-size: 20rpx;
|
|||
|
|
color: rgba(255, 255, 255, 0.8);
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 右下角悬浮相机按钮 - 仅物业人员可见 */
|
|||
|
|
.fab-camera {
|
|||
|
|
position: fixed;
|
|||
|
|
right: 40rpx;
|
|||
|
|
bottom: 120rpx;
|
|||
|
|
width: 112rpx;
|
|||
|
|
height: 112rpx;
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
box-shadow: 0 8rpx 28rpx rgba(0, 0, 0, 0.15);
|
|||
|
|
|
|||
|
|
.camera-img {
|
|||
|
|
width: 48rpx;
|
|||
|
|
height: 48rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|