staff/pagesB/permissions/villageList.vue

596 lines
13 KiB
Vue

<template>
<view class="container">
<!-- 自定义导航栏 -->
<wd-navbar :bordered="false"
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(20px) !important;"
safeAreaInsetTop fixed placeholder>
<template #left>
<view class="li-ml-15 li-mt-10 li-flex li-items-center">
<text v-if="hasMultiplePages" class="ri-arrow-left-s-line li-text-70"
@click="toPages({type:'nav'})"></text>
<text v-if="!hasMultiplePages" class="ri-home-5-line li-text-55 li-mb-8 li-mr-10"
@click="toPages({type:'home'})"></text>
<text class="li-text-42">小区列表</text>
</view>
</template>
</wd-navbar>
<!-- 导航栏背景 -->
<view class="nav-bg-layer"></view>
<!-- 页面背景 -->
<view class="page-bg"></view>
<view class="content">
<!-- 搜索区域 -->
<view class="search-wrapper li-w-90% li-mx-auto li-mt-30">
<wd-search placeholderStyle="color:#a0aec0" v-model="searchKeyword" placeholder="搜索小区名称或地址" hide-cancel
placeholder-left @search="handleSearch">
<!-- <template #prefix>
<text class="ri-search-line li-text-36 li-text-#4C84FF"></text>
</template> -->
</wd-search>
</view>
<!-- 小区列表 -->
<view class="village-list li-w-92% li-mx-auto li-mt-30">
<view class="village-card" v-for="(item, index) in villageList" :key="index"
@click="handleSelectVillage(item)">
<view class="card-header">
<view class="village-name">{{item.name}}</view>
<view class="badge-container">
<view class="badge li-mr-20">
<text class="badge-num">{{item.staffCount}}</text>
<text class="badge-text">员工</text>
</view>
<view class="badge">
<text class="badge-num">{{item.buildingCount}}</text>
<text class="badge-text">楼栋</text>
</view>
</view>
</view>
<view class="card-content">
<view class="village-address">
<text class="ri-map-pin-line address-icon"></text>
<text class="address-text">{{item.address}}</text>
</view>
<view class="village-action">
<text class="action-text">设置权限</text>
<text class="ri-arrow-right-s-line action-icon"></text>
</view>
</view>
<view class="card-footer">
<view class="footer-tag">
<text class="ri-building-2-line"></text>
<text>物业管理</text>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="villageList.length === 0" class="empty-state li-mt-100">
<wd-status-tip :image="uni.$globalData?.RESOURCE_URL+'tip/search.png'" tip="暂无小区数据" />
<view class="empty-action">
<wd-button type="primary" custom-class="add-village-btn" @click="handleAddVillage">添加小区</wd-button>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import {
ref
} from 'vue';
import {
useNavigation
} from '@/hooks/useNavigation';
import {
onLoad,
onPullDownRefresh,
onReachBottom
} from '@dcloudio/uni-app';
// 使用导航composable
const {
hasMultiplePages,
isTabBarPage,
checkRouteStack
} = useNavigation();
// 搜索关键词
const searchKeyword = ref('');
// 小区列表数据
const villageList = ref([{
id: 1,
name: '阳光花园小区',
address: '市政府北路123号',
staffCount: 12,
buildingCount: 8
},
{
id: 2,
name: '翠湖庭院',
address: '湖滨路456号',
staffCount: 8,
buildingCount: 5
},
{
id: 3,
name: '金色家园',
address: '市政府东路789号',
staffCount: 15,
buildingCount: 10
},
{
id: 4,
name: '铂金公寓',
address: '南山大道458号',
staffCount: 9,
buildingCount: 6
},
{
id: 5,
name: '滨江华府',
address: '滨河路367号',
staffCount: 18,
buildingCount: 14
}
]);
/**
* 处理搜索
*/
const handleSearch = () => {
console.log('搜索关键词:', searchKeyword.value);
// TODO: 实现搜索逻辑
};
/**
* 选择小区,前往权限设置页面
* @param {Object} village 小区数据
*/
const handleSelectVillage = (village) => {
// 跳转到员工列表页面
uni.navigateTo({
url: '/pagesB/permissions/staffList?villageId=' + village.id
});
};
/**
* 添加小区
*/
const handleAddVillage = () => {
// TODO: 实现添加小区的逻辑
uni.showToast({
title: '添加小区功能开发中',
icon: 'none'
});
};
// 页面跳转
const toPages = (item) => {
switch (item.type) {
case 'nav':
uni.navigateBack({
delta: 1
});
break;
case 'home':
uni.switchTab({
url: '/pages/index/index'
});
break;
default:
break;
}
};
// 生命周期钩子
onLoad(() => {
checkRouteStack();
});
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background-color: transparent;
position: relative;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica, Segoe UI, Arial, Roboto, PingFang SC, sans-serif;
}
.page-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #f8fafd 0%, #eef2f9 100%);
z-index: -2;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 30%;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.03), rgba(76, 132, 255, 0));
z-index: -1;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40%;
background: linear-gradient(315deg, rgba(76, 132, 255, 0.02), rgba(76, 132, 255, 0));
z-index: -1;
}
}
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.content {
position: relative;
z-index: 2;
padding-bottom: 30rpx;
/* #ifdef MP-WEIXIN */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
/* #endif */
/* #ifdef APP-PLUS || H5 */
padding-bottom: 50rpx;
/* #endif */
}
.search-wrapper {
position: relative;
z-index: 3;
margin-bottom: 40rpx;
&::before {
content: '';
position: absolute;
top: 50%;
left: -15%;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.1), rgba(76, 132, 255, 0));
z-index: -1;
transform: translateY(-50%);
}
&::after {
content: '';
position: absolute;
top: -20rpx;
right: -5%;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, rgba(66, 211, 170, 0.06), rgba(66, 211, 170, 0));
z-index: -1;
}
}
.village-list {
.village-card {
background-color: #fff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 10rpx 30rpx rgba(31, 35, 172, 0.05);
margin-bottom: 30rpx;
transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 6rpx;
height: 100%;
background: linear-gradient(180deg, #4C84FF, #6EAEFE);
opacity: 0;
transition: opacity 0.3s ease;
}
&:active {
transform: translateY(2rpx) scale(0.99);
box-shadow: 0 6rpx 15rpx rgba(31, 35, 172, 0.03);
&::before {
opacity: 1;
}
}
.card-header {
padding: 36rpx 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.06), rgba(76, 132, 255, 0.12));
border-bottom: 1rpx solid rgba(0, 0, 0, 0.03);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 200rpx;
height: 200rpx;
background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0));
z-index: 1;
}
.village-name {
font-size: 36rpx;
font-weight: 600;
color: #333;
position: relative;
z-index: 2;
background: linear-gradient(90deg, #333, #555);
-webkit-background-clip: text;
color: transparent;
letter-spacing: 1rpx;
}
.badge-container {
display: flex;
position: relative;
z-index: 2;
.badge {
display: flex;
flex-direction: column;
align-items: center;
background-color: rgba(76, 132, 255, 0.1);
padding: 10rpx 24rpx;
border-radius: 12rpx;
box-shadow: 0 4rpx 12rpx rgba(76, 132, 255, 0.1);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1rpx;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0));
}
.badge-num {
font-size: 30rpx;
font-weight: 600;
color: #4C84FF;
text-shadow: 0 1rpx 2rpx rgba(76, 132, 255, 0.1);
}
.badge-text {
font-size: 22rpx;
color: #666;
margin-top: 2rpx;
}
}
}
}
.card-content {
padding: 30rpx 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
&::before {
content: '';
position: absolute;
bottom: 0;
left: 40rpx;
right: 40rpx;
height: 1px;
background: linear-gradient(90deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.03), rgba(0, 0, 0, 0));
}
.village-address {
display: flex;
align-items: center;
.address-text {
font-size: 28rpx;
color: #666;
margin-left: 6rpx;
}
}
.village-action {
display: flex;
align-items: center;
background: rgba(76, 132, 255, 0.06);
padding: 10rpx 20rpx;
border-radius: 40rpx;
transition: all 0.3s ease;
&:active {
background: rgba(76, 132, 255, 0.1);
transform: translateX(-4rpx);
}
.action-text {
font-size: 26rpx;
color: #4C84FF;
margin-right: 8rpx;
font-weight: 500;
}
}
}
}
}
/* 覆盖组件样式 */
::v-deep .wd-search {
background-color: transparent !important;
padding: 0 !important;
}
::v-deep .wd-search__block {
background-color: rgba(255, 255, 255, 0.9) !important;
padding: 20rpx 30rpx !important;
border-radius: 20rpx !important;
box-shadow: 0 15rpx 30rpx rgba(31, 35, 172, 0.05);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1rpx solid rgba(255, 255, 255, 0.8);
}
::v-deep .wd-search__input {
font-size: 28rpx !important;
color: #333 !important;
}
::v-deep .wd-search__input-inner {
height: 70rpx !important;
}
::v-deep .wd-search__placeholder {
font-size: 28rpx !important;
}
::v-deep .wd-search__label {
color: #4C84FF !important;
}
::v-deep .wd-status-tip__text {
margin-top: 30rpx !important;
color: #999 !important;
font-size: 30rpx !important;
}
::v-deep .wd-status-tip__image {
opacity: 0.8 !important;
}
.page-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40rpx;
margin-top: 20rpx;
.title-wrapper {
.title-main {
font-size: 44rpx;
font-weight: 600;
color: #333;
margin-right: 15rpx;
background: linear-gradient(90deg, #333, #555);
-webkit-background-clip: text;
color: transparent;
}
.title-sub {
font-size: 28rpx;
color: #999;
margin-left: 15rpx;
}
}
.add-button {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, #4C84FF, #6EAEFE);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 6rpx 20rpx rgba(76, 132, 255, 0.3);
transition: all 0.3s ease;
&:active {
transform: scale(0.92);
box-shadow: 0 3rpx 10rpx rgba(76, 132, 255, 0.2);
}
text {
color: white;
font-size: 44rpx;
}
}
}
.address-icon {
color: #999;
font-size: 32rpx;
margin-right: 2rpx;
}
.action-icon {
color: #4C84FF;
font-size: 36rpx;
}
.card-footer {
padding: 20rpx 40rpx;
border-top: 1rpx solid rgba(0, 0, 0, 0.03);
background: #fafbfc;
.footer-tag {
display: inline-flex;
align-items: center;
background: rgba(76, 132, 255, 0.06);
padding: 6rpx 16rpx;
border-radius: 8rpx;
text:first-child {
color: #4C84FF;
font-size: 28rpx;
margin-right: 6rpx;
}
text:last-child {
font-size: 24rpx;
color: #666;
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
.empty-action {
margin-top: 40rpx;
}
}
.add-village-btn {
background: linear-gradient(135deg, #4C84FF, #6EAEFE) !important;
border: none !important;
box-shadow: 0 6rpx 20rpx rgba(76, 132, 255, 0.2) !important;
border-radius: 12rpx !important;
font-weight: 500 !important;
letter-spacing: 2rpx !important;
}
</style>