fjrcloud-community-app/pages/sub/community/daily.vue

303 lines
7.9 KiB
Vue
Raw Normal View History

<!-- 物业日常 - 打卡记录页面 -->
<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>