refactor(pages): 重组社区模块页面结构
parent
749af59a5d
commit
055dfcf3fd
95
pages.json
95
pages.json
|
|
@ -80,17 +80,7 @@
|
||||||
"group": "物业管理"
|
"group": "物业管理"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "pages/notice/detail",
|
|
||||||
"style": {
|
|
||||||
"navigationBarTitleText": "通知公告"
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"sync": true,
|
|
||||||
"title": "通知公告",
|
|
||||||
"group": "物业管理"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "pages/index/search",
|
"path": "pages/index/search",
|
||||||
"style": {
|
"style": {
|
||||||
|
|
@ -522,18 +512,6 @@
|
||||||
"title": "申请提现",
|
"title": "申请提现",
|
||||||
"group": "分销商城"
|
"group": "分销商城"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "message",
|
|
||||||
"style": {
|
|
||||||
"navigationBarTitleText": "消息通知"
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"auth": true,
|
|
||||||
"sync": true,
|
|
||||||
"title": "消息通知",
|
|
||||||
"group": "分销商城"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -602,9 +580,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"root": "pages/community",
|
"root": "pages/sub",
|
||||||
"pages": [{
|
"pages": [{
|
||||||
"path": "dynamics",
|
"path": "community/dynamics",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "社区动态"
|
"navigationBarTitleText": "社区动态"
|
||||||
},
|
},
|
||||||
|
|
@ -613,6 +591,73 @@
|
||||||
"title": "社区动态",
|
"title": "社区动态",
|
||||||
"group": "物业管理"
|
"group": "物业管理"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "notice/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "通知公告"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "通知公告",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "activity/list",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "小区活动"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "小区活动",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "activity/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "小区活动"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "小区活动",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "staff/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "物业人员"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "物业人员",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "knowledge/classroom",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "知识课堂"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "知识课堂",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "community/daily",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "物业日常",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,12 @@
|
||||||
/* 导航栏 */
|
/* 导航栏 */
|
||||||
.navbar {
|
.navbar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 88rpx;
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-top: env(safe-area-inset-top);
|
padding-top: calc(env(safe-area-inset-top) + 44rpx);
|
||||||
|
height: calc(44rpx + env(safe-area-inset-top));
|
||||||
|
|
||||||
.navbar-content {
|
.navbar-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
|
|
@ -125,12 +125,12 @@ const bannerList = ref([
|
||||||
|
|
||||||
// 功能入口列表
|
// 功能入口列表
|
||||||
const functionList = ref([
|
const functionList = ref([
|
||||||
{ label: '工作计划', icon: '/static/img/Group_1.png', bgGradient: 'linear-gradient(35deg, #FF7F69 0%, #FC5A5D 100%)', path: '/pages/community/dynamics' },
|
{ label: '工作计划', icon: '/static/img/Group_1.png', bgGradient: 'linear-gradient(35deg, #FF7F69 0%, #FC5A5D 100%)', path: '/pages/sub/community/dynamics' },
|
||||||
{ label: '业主投票', icon: '/static/img/Group_2.png', bgGradient: 'linear-gradient(35deg, #52C41A 0%, #36AD1A 100%)', path: '' },
|
{ label: '业主投票', icon: '/static/img/Group_2.png', bgGradient: 'linear-gradient(35deg, #52C41A 0%, #36AD1A 100%)', path: '/pages/sub/community/daily' },
|
||||||
{ label: '收益公示', icon: '/static/img/Group_3.png', bgGradient: 'linear-gradient(35deg, #FFA940 0%, #FA8C16 100%)', path: '' },
|
{ label: '收益公示', icon: '/static/img/Group_3.png', bgGradient: 'linear-gradient(35deg, #FFA940 0%, #FA8C16 100%)', path: '' },
|
||||||
{ label: '在线缴费', icon: '/static/img/Group_4.png', bgGradient: 'linear-gradient(35deg, #4096FF 0%, #1890FF 100%)', path: '' },
|
{ label: '在线缴费', icon: '/static/img/Group_4.png', bgGradient: 'linear-gradient(35deg, #4096FF 0%, #1890FF 100%)', path: '' },
|
||||||
{ label: '报事报修', icon: '/static/img/Group_5.png', bgGradient: 'linear-gradient(35deg, #69B1FF 0%, #4096FF 100%)', path: '' },
|
{ label: '报事报修', icon: '/static/img/Group_5.png', bgGradient: 'linear-gradient(35deg, #69B1FF 0%, #4096FF 100%)', path: '' },
|
||||||
{ label: '物业人员', icon: '/static/img/Group_6.png', bgGradient: 'linear-gradient(35deg, #9254DE 0%, #722ED1 100%)', path: '' },
|
{ label: '物业人员', icon: '/static/img/Group_6.png', bgGradient: 'linear-gradient(35deg, #9254DE 0%, #722ED1 100%)', path: '/pages/sub/staff/index' },
|
||||||
{ label: '业委会组织', icon: '/static/img/Group_7.png', bgGradient: 'linear-gradient(35deg, #7B61FF 0%, #597EF7 100%)', path: '' },
|
{ label: '业委会组织', icon: '/static/img/Group_7.png', bgGradient: 'linear-gradient(35deg, #7B61FF 0%, #597EF7 100%)', path: '' },
|
||||||
{ label: '更多服务', icon: '/static/img/Group_8.png', bgGradient: 'linear-gradient(35deg, #36CFC9 0%, #13C2C2 100%)', path: '' },
|
{ label: '更多服务', icon: '/static/img/Group_8.png', bgGradient: 'linear-gradient(35deg, #36CFC9 0%, #13C2C2 100%)', path: '' },
|
||||||
]);
|
]);
|
||||||
|
|
@ -152,7 +152,7 @@ const handleFunctionTap = (item) => {
|
||||||
|
|
||||||
// 通知
|
// 通知
|
||||||
const goNotice = () => {
|
const goNotice = () => {
|
||||||
uni.navigateTo({ url: '/pages/notice/detail?id=1' });
|
uni.navigateTo({ url: '/pages/sub/notice/detail?id=1' });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转登录页
|
// 跳转登录页
|
||||||
|
|
@ -166,22 +166,22 @@ const goCheck = () => {
|
||||||
|
|
||||||
// 法律小课堂
|
// 法律小课堂
|
||||||
const goLawClass = () => {
|
const goLawClass = () => {
|
||||||
uni.navigateTo({ url: '/pages/public/richtext?title=法律小课堂' });
|
uni.navigateTo({ url: '/pages/sub/knowledge/classroom?tab=0', fail: (err) => { console.error('跳转失败', err); } });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 小区治理
|
// 小区治理
|
||||||
const goCommunityGov = () => {
|
const goCommunityGov = () => {
|
||||||
uni.navigateTo({ url: '/pages/public/richtext?title=小区治理' });
|
uni.navigateTo({ url: '/pages/sub/knowledge/classroom?tab=1', fail: (err) => { console.error('跳转失败', err); } });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 活动列表
|
// 活动列表
|
||||||
const goActivityList = () => {
|
const goActivityList = () => {
|
||||||
uni.navigateTo({ url: '/pages/activity/index' });
|
uni.navigateTo({ url: '/pages/sub/activity/list' });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 活动详情
|
// 活动详情
|
||||||
const goActivityDetail = () => {
|
const goActivityDetail = () => {
|
||||||
uni.navigateTo({ url: '/pages/activity/detail' });
|
uni.navigateTo({ url: '/pages/sub/activity/detail?id=1' });
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
<image class="right-icon" src="/static/img/right-icon.png" mode="aspectFit" />
|
<image class="right-icon" src="/static/img/right-icon.png" mode="aspectFit" />
|
||||||
</view>
|
</view>
|
||||||
<view class="divider"></view>
|
<view class="divider"></view>
|
||||||
<view class="menu-item" @tap="navigateTo('/pages/commission/message')">
|
<view class="menu-item">
|
||||||
<view class="menu-item-left">
|
<view class="menu-item-left">
|
||||||
<image class="menu-icon" src="/static/img/me-icon2.png" mode="aspectFit" />
|
<image class="menu-icon" src="/static/img/me-icon2.png" mode="aspectFit" />
|
||||||
<text class="menu-label">消息通知</text>
|
<text class="menu-label">消息通知</text>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,237 @@
|
||||||
|
<!-- 社区动态页面 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="社区动态" navbar="inner">
|
||||||
|
<view class="community-dynamics-page">
|
||||||
|
<!-- Tab 切换栏 -->
|
||||||
|
<view class="tab-bar">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
v-for="(tab, index) in tabList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: currentTab === index }"
|
||||||
|
@tap="switchTab(index)"
|
||||||
|
>
|
||||||
|
<text class="tab-text">{{ tab }}</text>
|
||||||
|
<view class="tab-indicator" v-if="currentTab === index"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 动态列表 -->
|
||||||
|
<view class="dynamics-list">
|
||||||
|
<view
|
||||||
|
class="dynamics-item"
|
||||||
|
v-for="(item, index) in dynamicsList"
|
||||||
|
:key="index"
|
||||||
|
@tap="goDetail(item)"
|
||||||
|
>
|
||||||
|
<!-- 封面图 -->
|
||||||
|
<image class="item-cover" :src="item.cover" mode="aspectFill" />
|
||||||
|
|
||||||
|
<!-- 内容区 -->
|
||||||
|
<view class="item-content">
|
||||||
|
<text class="item-title">{{ item.title }}</text>
|
||||||
|
<view class="item-footer">
|
||||||
|
<text class="item-views">{{ item.views }}</text>
|
||||||
|
<text class="item-date">{{ item.date }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-if="dynamicsList.length === 0">
|
||||||
|
<text class="empty-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
|
||||||
|
// Tab 列表
|
||||||
|
const tabList = ref(['全部', '物业', '业委会', '社区']);
|
||||||
|
const currentTab = ref(0);
|
||||||
|
|
||||||
|
// 动态列表
|
||||||
|
const dynamicsList = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '1.2万播放',
|
||||||
|
date: '2021/02/21'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '1.2万播放',
|
||||||
|
date: '2021/02/21'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '1.2万播放',
|
||||||
|
date: '2021/02/21'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '1.2万播放',
|
||||||
|
date: '2021/02/21'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.tab) {
|
||||||
|
currentTab.value = parseInt(options.tab);
|
||||||
|
}
|
||||||
|
loadDynamicsList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 切换 Tab
|
||||||
|
function switchTab(index) {
|
||||||
|
currentTab.value = index;
|
||||||
|
loadDynamicsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载动态列表
|
||||||
|
async function loadDynamicsList() {
|
||||||
|
// TODO: 调用API获取动态列表
|
||||||
|
// const { code, data } = await DynamicsApi.getDynamicsList({ tab: currentTab.value });
|
||||||
|
// if (code === 0) {
|
||||||
|
// dynamicsList.value = data.list || [];
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转详情
|
||||||
|
function goDetail(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/public/community/dynamics-detail?id=${item.id}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 页面容器 */
|
||||||
|
.community-dynamics-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tab 切换栏 */
|
||||||
|
.tab-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
padding: 24rpx 0;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
position: relative;
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #999999;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active .tab-text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-indicator {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 48rpx;
|
||||||
|
height: 6rpx;
|
||||||
|
background: linear-gradient(90deg, #FF7F69 0%, #FC5A5D 100%);
|
||||||
|
border-radius: 3rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动态列表 */
|
||||||
|
.dynamics-list {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动态项 */
|
||||||
|
.dynamics-item {
|
||||||
|
display: flex;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.item-cover {
|
||||||
|
width: 240rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.5;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.item-views {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-date {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态 */
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 200rpx 0;
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,472 @@
|
||||||
|
<!-- 小区活动详情页 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="小区活动">
|
||||||
|
<view class="activity-detail-page">
|
||||||
|
<!-- 顶部Banner轮播 -->
|
||||||
|
<swiper class="banner-swiper" :autoplay="true" :interval="3000" :circular="true" indicator-dots indicator-color="rgba(255,255,255,0.4)" active-color="#FFFFFF">
|
||||||
|
<swiper-item v-for="(img, index) in activityInfo.banners" :key="index">
|
||||||
|
<image class="banner-img" :src="img" mode="aspectFill" />
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
|
||||||
|
<!-- Tab 切换栏 -->
|
||||||
|
<view class="tab-bar">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: currentTab === 'basic' }"
|
||||||
|
@tap="currentTab = 'basic'"
|
||||||
|
>
|
||||||
|
<text class="tab-text">基本信息</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: currentTab === 'intro' }"
|
||||||
|
@tap="currentTab = 'intro'"
|
||||||
|
>
|
||||||
|
<text class="tab-text">活动简介</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区域 - 独立滚动 -->
|
||||||
|
<scroll-view class="detail-scroll" scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
||||||
|
<view class="detail-content">
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<template v-if="currentTab === 'basic'">
|
||||||
|
<!-- 活动标题 -->
|
||||||
|
<view class="activity-title">{{ activityInfo.title }}</view>
|
||||||
|
|
||||||
|
<!-- 地址 -->
|
||||||
|
<view class="info-row location-row">
|
||||||
|
<text class="sicon-location"></text>
|
||||||
|
<text class="location-text">{{ activityInfo.location }}</text>
|
||||||
|
<text class="sicon-right navigation-icon" @tap="openNavigation"></text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 服务类别 -->
|
||||||
|
<view class="info-row tag-row">
|
||||||
|
<text class="label-text">服务类别:</text>
|
||||||
|
<view class="tag-list">
|
||||||
|
<text
|
||||||
|
class="tag-item"
|
||||||
|
v-for="(tag, index) in activityInfo.serviceTypes"
|
||||||
|
:key="index"
|
||||||
|
>{{ tag }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 服务对象 -->
|
||||||
|
<view class="info-row tag-row">
|
||||||
|
<text class="label-text">服务对象:</text>
|
||||||
|
<view class="tag-list">
|
||||||
|
<text
|
||||||
|
class="tag-item target-tag"
|
||||||
|
v-for="(tag, index) in activityInfo.targetAudience"
|
||||||
|
:key="index"
|
||||||
|
>{{ tag }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 报名日期 -->
|
||||||
|
<view class="info-row text-row">
|
||||||
|
<text class="label-text">报名日期:</text>
|
||||||
|
<text class="value-text">{{ activityInfo.registerDate }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 活动日期 -->
|
||||||
|
<view class="info-row text-row">
|
||||||
|
<text class="label-text">活动日期:</text>
|
||||||
|
<text class="value-text">{{ activityInfo.activityDate }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 人数上限 -->
|
||||||
|
<view class="info-row text-row">
|
||||||
|
<text class="sicon-person"></text>
|
||||||
|
<text class="label-text">人数上限:</text>
|
||||||
|
<text class="value-text">{{ activityInfo.maxPeople }}人</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 联系人 -->
|
||||||
|
<view class="info-row contact-row" @tap="callPhone">
|
||||||
|
<text class="sicon-phone"></text>
|
||||||
|
<text class="contact-name">{{ activityInfo.contactName }}</text>
|
||||||
|
<text class="contact-phone">{{ activityInfo.contactPhone }}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 活动简介 -->
|
||||||
|
<template v-if="currentTab === 'intro'">
|
||||||
|
<view class="intro-content">
|
||||||
|
<mp-html :content="activityInfo.introduction"></mp-html>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 底部占位,防止内容被底部按钮遮挡 -->
|
||||||
|
<view class="bottom-placeholder"></view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 底部固定按钮栏 -->
|
||||||
|
<view class="bottom-bar">
|
||||||
|
<view class="registered-btn" @tap="showRegisteredList">
|
||||||
|
<text class="registered-text">已有{{ activityInfo.registeredCount }}人报名</text>
|
||||||
|
</view>
|
||||||
|
<view class="back-btn" @tap="goBack">
|
||||||
|
<text class="back-text">返回</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
|
||||||
|
// 当前Tab
|
||||||
|
const currentTab = ref('basic');
|
||||||
|
|
||||||
|
// 列表滚动区域高度(单位:px)
|
||||||
|
const scrollViewHeight = ref(0);
|
||||||
|
|
||||||
|
// 活动详情数据
|
||||||
|
const activityInfo = ref({
|
||||||
|
id: null,
|
||||||
|
title: '',
|
||||||
|
banners: [],
|
||||||
|
location: '',
|
||||||
|
serviceTypes: [],
|
||||||
|
targetAudience: [],
|
||||||
|
registerDate: '',
|
||||||
|
activityDate: '',
|
||||||
|
maxPeople: 0,
|
||||||
|
contactName: '',
|
||||||
|
contactPhone: '',
|
||||||
|
registeredCount: 0,
|
||||||
|
introduction: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.id) {
|
||||||
|
loadActivityDetail(options.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 渲染完成后计算scroll-view高度
|
||||||
|
onMounted(() => {
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
nextTick(() => {
|
||||||
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(instance)
|
||||||
|
.select('.tab-bar')
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
if (rect) {
|
||||||
|
// scroll-view高度 = 屏幕可用高度 - tab栏高度 - tab栏距顶部距离 - 底部按钮高度(120rpx)
|
||||||
|
scrollViewHeight.value = sysInfo.windowHeight - rect.height - rect.top - 60;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载活动详情
|
||||||
|
async function loadActivityDetail(id) {
|
||||||
|
// TODO: 调用API获取活动详情
|
||||||
|
// 模拟数据
|
||||||
|
activityInfo.value = {
|
||||||
|
id: id,
|
||||||
|
title: 'xxxxxxxxxxxxxxxxx活动',
|
||||||
|
banners: [
|
||||||
|
'/static/img/guest.png',
|
||||||
|
'/static/img/login_img.png'
|
||||||
|
],
|
||||||
|
location: '福清市音西街道',
|
||||||
|
serviceTypes: ['社区服务', '敬老服务', '助残服务', '关爱儿童'],
|
||||||
|
targetAudience: ['儿童', '孤寡老人', '残障人士', '优抚对象'],
|
||||||
|
registerDate: '2025/06/30-2025/07/01',
|
||||||
|
activityDate: '2025/07/05 12:00-2025/07/05 18:00',
|
||||||
|
maxPeople: 100,
|
||||||
|
contactName: '王德福',
|
||||||
|
contactPhone: '13322471131',
|
||||||
|
registeredCount: 37,
|
||||||
|
introduction: `<p>本次活动旨在丰富社区居民文化生活,增进邻里关系,共建和谐社区。</p><p>欢迎各位居民踊跃参与!</p>`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开导航
|
||||||
|
function openNavigation() {
|
||||||
|
// TODO: 调用地图导航
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拨打电话
|
||||||
|
function callPhone() {
|
||||||
|
if (activityInfo.value.contactPhone) {
|
||||||
|
uni.makePhoneCall({
|
||||||
|
phoneNumber: activityInfo.value.contactPhone
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示已报名列表
|
||||||
|
function showRegisteredList() {
|
||||||
|
// TODO: 弹出已报名人员列表或跳转页面
|
||||||
|
uni.showToast({
|
||||||
|
title: '查看报名名单',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
function goBack() {
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 页面容器 */
|
||||||
|
.activity-detail-page {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 顶部Banner轮播 */
|
||||||
|
.banner-swiper {
|
||||||
|
width: 100%;
|
||||||
|
height: 400rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 400rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tab 切换栏 */
|
||||||
|
.tab-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
padding: 0 32rpx;
|
||||||
|
border-bottom: 1rpx solid #F0F0F0;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 28rpx 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #999999;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 120rpx;
|
||||||
|
height: 4rpx;
|
||||||
|
background: #FA7E49;
|
||||||
|
border-radius: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active .tab-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容滚动区域 */
|
||||||
|
.detail-scroll {
|
||||||
|
/* 高度由JS动态绑定 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 详情内容 */
|
||||||
|
.detail-content {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 活动标题 */
|
||||||
|
.activity-title {
|
||||||
|
padding: 32rpx 32rpx 16rpx;
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #FA7E49;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 信息行 */
|
||||||
|
.info-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 20rpx 32rpx;
|
||||||
|
|
||||||
|
.sicon-location,
|
||||||
|
.sicon-phone,
|
||||||
|
.sicon-person {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #666666;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
margin-top: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 地址行 */
|
||||||
|
.location-row {
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.location-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-icon {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #FA7E49;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 标签行 */
|
||||||
|
.tag-row {
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.label-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex-shrink: 0;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12rpx;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-item {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #FA7E49;
|
||||||
|
border: 1rpx solid #FA7E49;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 6rpx 16rpx;
|
||||||
|
background-color: rgba(250, 126, 73, 0.04);
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.target-tag {
|
||||||
|
color: #FA7E49;
|
||||||
|
border: 1rpx solid #FA7E49;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 文本行 */
|
||||||
|
.text-row {
|
||||||
|
.label-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 联系人行 */
|
||||||
|
.contact-row {
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-left: 8rpx;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-phone {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 活动简介内容 */
|
||||||
|
.intro-content {
|
||||||
|
padding: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部占位 */
|
||||||
|
.bottom-placeholder {
|
||||||
|
height: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部固定按钮栏 */
|
||||||
|
.bottom-bar {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24rpx;
|
||||||
|
padding: 20rpx 32rpx;
|
||||||
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.registered-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 88rpx;
|
||||||
|
border: 2rpx solid #FA7E49;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.registered-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #FA7E49;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-btn {
|
||||||
|
width: 240rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #FA7E49;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,331 @@
|
||||||
|
<!-- 小区活动列表页 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="小区活动">
|
||||||
|
<view class="activity-list-page">
|
||||||
|
<!-- 渐变背景装饰 -->
|
||||||
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
|
<!-- 固定头部区域 -->
|
||||||
|
<view class="list-header">
|
||||||
|
<!-- 顶部提示条 -->
|
||||||
|
<view class="top-banner">
|
||||||
|
<text class="banner-text">融侨馨苑开展活动啦!!</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 活动列表 - 独立滚动 -->
|
||||||
|
<scroll-view class="activity-scroll" scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
||||||
|
<view class="list-inner">
|
||||||
|
<view
|
||||||
|
class="activity-item"
|
||||||
|
v-for="(item, index) in activityList"
|
||||||
|
:key="index"
|
||||||
|
@tap="goDetail(item)"
|
||||||
|
>
|
||||||
|
<!-- 左侧封面图 -->
|
||||||
|
<image class="item-cover" :src="item.cover" mode="aspectFill" />
|
||||||
|
|
||||||
|
<!-- 右侧内容区 -->
|
||||||
|
<view class="item-content">
|
||||||
|
<text class="item-title">{{ item.title }}</text>
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-location">{{ item.location }}</text>
|
||||||
|
<text class="item-status" :class="'status-' + item.statusType">{{ item.statusText }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-label">报名日期:</text>
|
||||||
|
<text class="item-value">{{ item.registerDate }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-date">{{ item.dateRange }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-if="activityList.length === 0">
|
||||||
|
<text class="empty-text">暂无活动</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 右下角浮动按钮 -->
|
||||||
|
<view class="float-btn" @tap="handleFloatBtn">
|
||||||
|
<text class="sicon-edit"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
|
||||||
|
// 列表滚动区域高度(单位:px)
|
||||||
|
const scrollViewHeight = ref(0);
|
||||||
|
|
||||||
|
// 活动列表数据
|
||||||
|
const activityList = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: 'xxxxxxxxxxxxx活动',
|
||||||
|
location: '福清市音西街道融侨馨苑',
|
||||||
|
statusText: '进行中',
|
||||||
|
statusType: 'ongoing',
|
||||||
|
registerDate: '2025/06/30-2025/07/01',
|
||||||
|
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
||||||
|
cover: '/static/img/guest.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: 'xxxxxxxxxxxxx活动',
|
||||||
|
location: '福清市音西街道融侨馨苑',
|
||||||
|
statusText: '报名中',
|
||||||
|
statusType: 'registering',
|
||||||
|
registerDate: '2025/06/30-2025/07/01',
|
||||||
|
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
||||||
|
cover: '/static/img/guest.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: 'xxxxxxxxxxxxx活动',
|
||||||
|
location: '福清市音西街道融侨馨苑',
|
||||||
|
statusText: '已结束',
|
||||||
|
statusType: 'ended',
|
||||||
|
registerDate: '2025/06/30-2025/07/01',
|
||||||
|
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
||||||
|
cover: '/static/img/guest.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: 'xxxxxxxxxxxxx活动',
|
||||||
|
location: '福清市音西街道融侨馨苑',
|
||||||
|
statusText: '已结束',
|
||||||
|
statusType: 'ended',
|
||||||
|
registerDate: '2025/06/30-2025/07/01',
|
||||||
|
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
||||||
|
cover: '/static/img/guest.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: 'xxxxxxxxxxxxx活动',
|
||||||
|
location: '福清市音西街道融侨馨苑',
|
||||||
|
statusText: '已结束',
|
||||||
|
statusType: 'ended',
|
||||||
|
registerDate: '2025/06/30-2025/07/01',
|
||||||
|
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
||||||
|
cover: '/static/img/guest.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: 'xxxxxxxxxxxxx活动',
|
||||||
|
location: '福清市音西街道融侨馨苑',
|
||||||
|
statusText: '已结束',
|
||||||
|
statusType: 'ended',
|
||||||
|
registerDate: '2025/06/30-2025/07/01',
|
||||||
|
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
||||||
|
cover: '/static/img/guest.png'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad(() => {
|
||||||
|
loadActivityList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 渲染完成后计算scroll-view高度
|
||||||
|
onMounted(() => {
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
nextTick(() => {
|
||||||
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(instance)
|
||||||
|
.select('.list-header')
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
if (rect) {
|
||||||
|
// scroll-view高度 = 屏幕可用高度 - 头部区域高度 - 头部距顶部距离
|
||||||
|
scrollViewHeight.value = sysInfo.windowHeight - rect.height - rect.top;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载活动列表
|
||||||
|
async function loadActivityList() {
|
||||||
|
// TODO: 调用API获取活动列表
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转详情
|
||||||
|
function goDetail(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/sub/activity/detail?id=${item.id}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 浮动按钮点击
|
||||||
|
function handleFloatBtn() {
|
||||||
|
// TODO: 发布活动或跳转相关页面
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 页面容器 - flex布局:头部固定 + 列表滚动 */
|
||||||
|
.activity-list-page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 渐变背景装饰 - 覆盖导航栏到内容区 */
|
||||||
|
.gradient-bg {
|
||||||
|
position: absolute;
|
||||||
|
top: -176rpx; /* 向上延伸覆盖inner-navbar */
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: calc(100% + 176rpx);
|
||||||
|
background: linear-gradient(180deg, #F8EDE8 0%, #FFFFFF 30%);
|
||||||
|
z-index: -1; /* 在内容层下方 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 固定头部区域 */
|
||||||
|
.list-header {
|
||||||
|
flex-shrink: 0; /* 不被压缩,固定不动 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 顶部提示条 */
|
||||||
|
.top-banner {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
|
||||||
|
.banner-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #FA7E49;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 活动列表滚动区域 - 高度由JS动态绑定 */
|
||||||
|
.activity-scroll {
|
||||||
|
flex: 1; /* 占据剩余空间 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表内容包裹层 */
|
||||||
|
.list-inner {
|
||||||
|
padding: 0 32rpx 160rpx; /* 底部留出空间给浮动按钮 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 活动卡片 */
|
||||||
|
.activity-item {
|
||||||
|
display: flex;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.item-cover {
|
||||||
|
width: 220rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #FA7E49;
|
||||||
|
line-height: 1.4;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-location {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态标签颜色
|
||||||
|
.item-status {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&.status-ongoing { color: #52C41A; } // 进行中-绿色
|
||||||
|
&.status-registering { color: #FAAD14; } // 报名中-橙色
|
||||||
|
&.status-ended { color: #999999; } // 已结束-灰色
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-value {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-date {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态 */
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 200rpx 0;
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 右下角浮动按钮 */
|
||||||
|
.float-btn {
|
||||||
|
position: fixed;
|
||||||
|
right: 40rpx;
|
||||||
|
bottom: 80rpx;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
background: linear-gradient(135deg, #FA7E49 0%, #E86935 100%);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 8rpx 24rpx rgba(250, 126, 73, 0.4);
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.85;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sicon-edit {
|
||||||
|
font-size: 44rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,302 @@
|
||||||
|
<!-- 物业日常 - 打卡记录页面 -->
|
||||||
|
<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>
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<!-- 社区动态页面 -->
|
<!-- 社区动态页面 -->
|
||||||
<template>
|
<template>
|
||||||
<s-layout title="社区动态" :bgStyle="{ backgroundColor:'#F8EDE8' }" navbar="inner" color="#333333">
|
<s-layout title="社区动态" navbar="inner" color="#333333">
|
||||||
|
<!-- 渐变背景 -->
|
||||||
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
<view class="community-dynamics-page">
|
<view class="community-dynamics-page">
|
||||||
<!-- Tab 切换栏 -->
|
<!-- Tab 切换栏 -->
|
||||||
|
|
@ -154,25 +156,28 @@ async function loadDynamicsList() {
|
||||||
// 跳转详情
|
// 跳转详情
|
||||||
function goDetail(item) {
|
function goDetail(item) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/community/dynamics-detail?id=${item.id}`
|
url: `/pages/sub/community/dynamics-detail?id=${item.id}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
/* 页面容器 - 伪元素渐变向上覆盖到导航栏 */
|
/* 渐变背景 */
|
||||||
|
.gradient-bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 750rpx;
|
||||||
|
height: 660rpx;
|
||||||
|
background: linear-gradient(180deg, #F8EDE8 0%, #F5F5F5 50%);
|
||||||
|
z-index: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 页面容器 */
|
||||||
.community-dynamics-page {
|
.community-dynamics-page {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
&::before {
|
|
||||||
// content: '';
|
|
||||||
// position: absolute;
|
|
||||||
// left: 0;
|
|
||||||
// right: 0;
|
|
||||||
// height: calc(100% + 176rpx);
|
|
||||||
background: linear-gradient(180deg, #F8EDE8 0%, #FFFFFF 30%);
|
|
||||||
// z-index: -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tab 切换栏 */
|
/* Tab 切换栏 */
|
||||||
|
|
@ -0,0 +1,396 @@
|
||||||
|
<!-- 知识课堂页面 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="知识课堂" navbar="inner" color="#333333">
|
||||||
|
<!-- 渐变背景 -->
|
||||||
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
|
<view class="knowledge-classroom-page">
|
||||||
|
<!-- Tab 切换栏 -->
|
||||||
|
<view class="tab-bar">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
v-for="(tab, index) in tabList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: currentTab === index }"
|
||||||
|
@tap="switchTab(index)"
|
||||||
|
>
|
||||||
|
<text class="tab-text">{{ tab }}</text>
|
||||||
|
<view class="tab-indicator" v-if="currentTab === index"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表区域 - 独立滚动区域 -->
|
||||||
|
<scroll-view class="classroom-list" scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
||||||
|
<view class="list-inner" :class="{ 'grid-layout': currentTab === 1 }">
|
||||||
|
<view
|
||||||
|
class="classroom-item"
|
||||||
|
v-for="(item, index) in classroomList"
|
||||||
|
:key="index"
|
||||||
|
@tap="goDetail(item)"
|
||||||
|
>
|
||||||
|
<!-- 封面图 -->
|
||||||
|
<view class="item-cover-wrap">
|
||||||
|
<image class="item-cover" :src="item.cover" mode="aspectFill" />
|
||||||
|
<view class="play-icon" v-if="currentTab === 1">
|
||||||
|
<image class="play-img" src="/static/img/play-icon.png" mode="aspectFit" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区 -->
|
||||||
|
<view class="item-content">
|
||||||
|
<text class="item-title">{{ item.title }}</text>
|
||||||
|
<view class="item-footer" v-if="currentTab === 0">
|
||||||
|
<text class="item-date">{{ item.date }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-footer" v-else>
|
||||||
|
<view class="item-stat">
|
||||||
|
<text class="stat-icon">👁</text>
|
||||||
|
<text class="stat-text">{{ item.views }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-stat">
|
||||||
|
<text class="stat-icon">♡</text>
|
||||||
|
<text class="stat-text">{{ item.likes }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-if="classroomList.length === 0">
|
||||||
|
<text class="empty-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
|
||||||
|
// 列表滚动区域高度(单位:px),通过JS计算后绑定到scroll-view
|
||||||
|
const scrollViewHeight = ref(0);
|
||||||
|
|
||||||
|
// Tab 列表
|
||||||
|
const tabList = ref(['法律小课堂', '小区治理']);
|
||||||
|
const currentTab = ref(0);
|
||||||
|
|
||||||
|
// 知识课堂列表
|
||||||
|
const classroomList = ref([]);
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.tab) {
|
||||||
|
currentTab.value = parseInt(options.tab);
|
||||||
|
}
|
||||||
|
loadClassroomList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 页面渲染完成后,计算scroll-view的精确高度
|
||||||
|
onMounted(() => {
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
nextTick(() => {
|
||||||
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
// 获取tab栏的实际渲染高度
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(instance)
|
||||||
|
.select('.tab-bar')
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
if (rect) {
|
||||||
|
// scroll-view高度 = 屏幕可用高度 - tab栏高度 - tab栏距离顶部的高度
|
||||||
|
scrollViewHeight.value = sysInfo.windowHeight - rect.height - rect.top;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 切换 Tab
|
||||||
|
function switchTab(index) {
|
||||||
|
currentTab.value = index;
|
||||||
|
loadClassroomList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载知识课堂列表
|
||||||
|
async function loadClassroomList() {
|
||||||
|
// TODO: 调用API获取列表
|
||||||
|
// 模拟数据
|
||||||
|
if (currentTab.value === 0) {
|
||||||
|
// 法律小课堂 - 列表样式
|
||||||
|
classroomList.value = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX法规解读',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
date: '2025/07/05 12:00'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX法规解读',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
date: '2025/07/05 12:00'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX法规解读',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
date: '2025/07/05 12:00'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX法规解读',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
date: '2025/07/05 12:00'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// 小区治理 - 网格样式
|
||||||
|
classroomList.value = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX视频',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '154',
|
||||||
|
likes: '154'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX视频',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '154',
|
||||||
|
likes: '154'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX视频',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '154',
|
||||||
|
likes: '154'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX视频',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '154',
|
||||||
|
likes: '154'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX视频',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '154',
|
||||||
|
likes: '154'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX视频',
|
||||||
|
cover: '/static/img/guest.png',
|
||||||
|
views: '154',
|
||||||
|
likes: '154'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转详情
|
||||||
|
function goDetail(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/sub/knowledge/detail?id=${item.id}&tab=${currentTab.value}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 渐变背景 */
|
||||||
|
.gradient-bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 750rpx;
|
||||||
|
height: 660rpx;
|
||||||
|
background: linear-gradient(180deg, #F8EDE8 0%, #F5F5F5 50%);
|
||||||
|
z-index: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 页面容器 */
|
||||||
|
.knowledge-classroom-page {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tab 切换栏 */
|
||||||
|
.tab-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 36rpx 50rpx;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
position: relative;
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #999999;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active .tab-text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-indicator {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 48rpx;
|
||||||
|
height: 6rpx;
|
||||||
|
background: linear-gradient(90deg, #FF7F69 0%, #FC5A5D 100%);
|
||||||
|
border-radius: 3rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表 - scroll-view,高度由JS动态绑定 */
|
||||||
|
.classroom-list {
|
||||||
|
/* 高度由 :style="{ height: scrollViewHeight + 'px' }" 控制 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表内容包裹层 - 负责padding间距 */
|
||||||
|
.list-inner {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
|
||||||
|
&.grid-layout {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 知识课堂项 */
|
||||||
|
.classroom-item {
|
||||||
|
display: flex;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 19rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.grid-layout & {
|
||||||
|
width: 335rpx;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-cover-wrap {
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.grid-layout & {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-cover {
|
||||||
|
width: 305rpx;
|
||||||
|
height: 168rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
|
||||||
|
.grid-layout & {
|
||||||
|
width: 100%;
|
||||||
|
height: 200rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.play-img {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.grid-layout & {
|
||||||
|
margin-left: 0;
|
||||||
|
padding: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.5;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
|
||||||
|
.item-date {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-stat {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态 */
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 200rpx 0;
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
<!-- 通知公告详情页 -->
|
<!-- 通知公告详情页 -->
|
||||||
<template>
|
<template>
|
||||||
<s-layout title="通知公告" :bgStyle="{ backgroundColor:'#F8EDE8' }" navbar="inner" color="#333333">
|
<s-layout title="通知公告" navbar="inner" color="#333333">
|
||||||
<!-- 页面主体:flex布局,头部固定+内容滚动 -->
|
<!-- 渐变背景 -->
|
||||||
<view class="notice-detail-page">
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
<!-- 固定头部区域 -->
|
<!-- 固定头部区域 -->
|
||||||
<view class="detail-header">
|
<view class="detail-header">
|
||||||
|
<view class="header-inner">
|
||||||
<!-- 文章标题 -->
|
<!-- 文章标题 -->
|
||||||
<view class="article-title">
|
<view class="article-title">
|
||||||
<text class="title-text">{{ noticeInfo.title }}</text>
|
<text class="title-text">{{ noticeInfo.title }}</text>
|
||||||
|
|
@ -22,20 +24,22 @@
|
||||||
<!-- 分割线 -->
|
<!-- 分割线 -->
|
||||||
<view class="divider"></view>
|
<view class="divider"></view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 富文本内容 - 独立滚动区域 -->
|
<!-- 富文本内容 - 独立滚动区域 -->
|
||||||
<scroll-view class="article-scroll" scroll-y :style="{ height: contentScrollHeight + 'px' }">
|
<scroll-view class="article-scroll" scroll-y :style="{ height: contentScrollHeight + 'px', top: contentScrollTop + 'px' }">
|
||||||
<view class="article-content">
|
<view class="article-content">
|
||||||
|
<view class="article-inner">
|
||||||
<mp-html :content="noticeInfo.content"></mp-html>
|
<mp-html :content="noticeInfo.content"></mp-html>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
<!-- 占位,防止内容被底部附件遮挡 -->
|
<!-- 占位,防止内容被底部附件遮挡 -->
|
||||||
<view class="bottom-placeholder" v-if="noticeInfo.attachments && noticeInfo.attachments.length > 0"></view>
|
<view class="bottom-placeholder" v-if="noticeInfo.attachments && noticeInfo.attachments.length > 0"></view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 附件列表 - 固定在底部 -->
|
<!-- 附件列表 - 固定在底部 -->
|
||||||
<view class="attachment-section" v-if="noticeInfo.attachments && noticeInfo.attachments.length > 0">
|
<view class="attachment-section" v-if="noticeInfo.attachments && noticeInfo.attachments.length > 0">
|
||||||
|
<view class="attachment-inner">
|
||||||
<view
|
<view
|
||||||
class="attachment-item"
|
class="attachment-item"
|
||||||
v-for="(item, index) in noticeInfo.attachments"
|
v-for="(item, index) in noticeInfo.attachments"
|
||||||
|
|
@ -49,6 +53,7 @@
|
||||||
<image class="download-icon" src="/static/img/right-icon.png" mode="aspectFit" />
|
<image class="download-icon" src="/static/img/right-icon.png" mode="aspectFit" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
</s-layout>
|
</s-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -59,6 +64,8 @@ import sheep from '@/sheep';
|
||||||
|
|
||||||
// 富文本滚动区域高度(单位:px)
|
// 富文本滚动区域高度(单位:px)
|
||||||
const contentScrollHeight = ref(0);
|
const contentScrollHeight = ref(0);
|
||||||
|
// 富文本滚动区域距离顶部的距离(单位:px)
|
||||||
|
const contentScrollTop = ref(0);
|
||||||
|
|
||||||
// 公告信息
|
// 公告信息
|
||||||
const noticeInfo = ref({
|
const noticeInfo = ref({
|
||||||
|
|
@ -76,21 +83,34 @@ onLoad((options) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 渲染完成后计算scroll-view高度(头部固定,剩余空间给内容滚动)
|
// 渲染完成后计算scroll-view高度和位置
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const sysInfo = uni.getSystemInfoSync();
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
uni.createSelectorQuery()
|
const query = uni.createSelectorQuery().in(instance);
|
||||||
.in(instance)
|
|
||||||
.select('.detail-header')
|
// 获取头部高度和位置
|
||||||
.boundingClientRect((rect) => {
|
query.select('.detail-header').boundingClientRect();
|
||||||
if (rect) {
|
// 获取附件区域高度(如果存在)
|
||||||
// scroll-view高度 = 屏幕可用高度 - 头部高度 - 头部距离顶部距离
|
query.select('.attachment-section').boundingClientRect();
|
||||||
contentScrollHeight.value = sysInfo.windowHeight - rect.height - rect.top;
|
|
||||||
|
query.exec((res) => {
|
||||||
|
const headerRect = res[0];
|
||||||
|
const attachmentRect = res[1];
|
||||||
|
|
||||||
|
let attachmentHeight = 0;
|
||||||
|
if (attachmentRect && attachmentRect.height > 0) {
|
||||||
|
attachmentHeight = attachmentRect.height;
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.exec();
|
if (headerRect) {
|
||||||
|
// scroll-view距离顶部 = 头部高度 + 头部距离顶部距离(已包含状态栏和导航栏高度)
|
||||||
|
contentScrollTop.value = headerRect.height + headerRect.top;
|
||||||
|
// scroll-view高度 = 屏幕可用高度 - scroll-view距离顶部 - 附件高度
|
||||||
|
contentScrollHeight.value = sysInfo.windowHeight - contentScrollTop.value - attachmentHeight;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -112,6 +132,24 @@ async function loadNoticeDetail(id) {
|
||||||
<p>一、会议基本信息</p>
|
<p>一、会议基本信息</p>
|
||||||
<p>会议时间:2026年2月15日(周六)上午9:00</p>
|
<p>会议时间:2026年2月15日(周六)上午9:00</p>
|
||||||
<p>会议地点:小区活动中心一楼会议室</p>
|
<p>会议地点:小区活动中心一楼会议室</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
|
<p>参会人员:全体业主或业主代表</p>
|
||||||
<p>参会人员:全体业主或业主代表</p>`,
|
<p>参会人员:全体业主或业主代表</p>`,
|
||||||
attachments: [
|
attachments: [
|
||||||
{ name: 'IMG-2309.PNG', type: 'image', url: '' },
|
{ name: 'IMG-2309.PNG', type: 'image', url: '' },
|
||||||
|
|
@ -202,21 +240,35 @@ function downloadAttachment(item) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
/* 页面容器 - 伪元素渐变向上覆盖到导航栏 */
|
/* 渐变背景 */
|
||||||
|
.gradient-bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 750rpx;
|
||||||
|
height: 660rpx;
|
||||||
|
background: linear-gradient(180deg, #F8EDE8 0%, #F5F5F5 50%);
|
||||||
|
z-index: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 页面容器 */
|
||||||
.notice-detail-page {
|
.notice-detail-page {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
z-index: 1;
|
||||||
flex-direction: column;
|
|
||||||
padding: 0 32rpx;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
background: linear-gradient(180deg, #F8EDE8 0%, #FFFFFF 30%);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 固定头部区域(标题+发布信息) */
|
/* 固定头部区域(标题+发布信息) */
|
||||||
.detail-header {
|
.detail-header {
|
||||||
flex-shrink: 0; /* 不被压缩 */
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 750rpx;
|
||||||
|
z-index: 10;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-inner {
|
||||||
|
padding: 0 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部占位 */
|
/* 底部占位 */
|
||||||
|
|
@ -275,13 +327,22 @@ function downloadAttachment(item) {
|
||||||
|
|
||||||
/* 富文本滚动区域 - 高度由JS动态绑定 */
|
/* 富文本滚动区域 - 高度由JS动态绑定 */
|
||||||
.article-scroll {
|
.article-scroll {
|
||||||
flex: 1; /* 占据剩余空间 */
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 富文本内容 */
|
/* 富文本内容 - 圆角背景卡片 */
|
||||||
.article-content {
|
.article-content {
|
||||||
|
margin: 0 32rpx;
|
||||||
border-radius: 24rpx;
|
border-radius: 24rpx;
|
||||||
padding: 32rpx;
|
// background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 富文本内容内层 - 控制padding */
|
||||||
|
.article-inner {
|
||||||
|
// padding: 32rpx;
|
||||||
|
|
||||||
:deep(p) {
|
:deep(p) {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
|
|
@ -302,13 +363,17 @@ function downloadAttachment(item) {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 750rpx;
|
width: 100%;
|
||||||
height: 300rpx;
|
height: 260rpx;
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
box-shadow: 0rpx -8rpx 64rpx 0rpx rgba(0, 0, 0, 0.16);
|
box-shadow: 0rpx -8rpx 64rpx 0rpx rgba(0, 0, 0, 0.16);
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
padding: 24rpx 32rpx;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-inner {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment-item {
|
.attachment-item {
|
||||||
|
|
@ -0,0 +1,509 @@
|
||||||
|
<!-- 物业人员页面 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="物业人员" :bgStyle="{ backgroundColor:'#F8EDE8' }" navbar="inner" color="#333333">
|
||||||
|
<view class="staff-page">
|
||||||
|
<!-- 渐变背景装饰 -->
|
||||||
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
|
<!-- 固定头部:统计卡片+分类Tab -->
|
||||||
|
<view class="page-header">
|
||||||
|
<!-- 统计卡片 -->
|
||||||
|
<view class="stats-card">
|
||||||
|
<!-- 小区名称 -->
|
||||||
|
<view class="card-top">
|
||||||
|
<view class="building-info">
|
||||||
|
<text class="sicon-building building-icon"></text>
|
||||||
|
<text class="building-name">{{ statsInfo.buildingName }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="staff-badge">物业人员</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 总人数 -->
|
||||||
|
<view class="total-row">
|
||||||
|
<text class="total-label">总人数</text>
|
||||||
|
<text class="total-count">{{ statsInfo.total }}<text class="total-unit">人</text></text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分类统计 -->
|
||||||
|
<view class="category-row">
|
||||||
|
<view
|
||||||
|
class="category-item"
|
||||||
|
v-for="(cat, index) in statsInfo.categories"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<text class="cat-name">{{ cat.name }}</text>
|
||||||
|
<text class="cat-count">{{ cat.count }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分类Tab栏 -->
|
||||||
|
<scroll-view class="tab-scroll" scroll-x :show-scrollbar="false">
|
||||||
|
<view class="tab-bar">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: currentTab === tab.key }"
|
||||||
|
v-for="(tab, index) in tabList"
|
||||||
|
:key="index"
|
||||||
|
@tap="currentTab = tab.key"
|
||||||
|
>
|
||||||
|
<text class="tab-text">{{ tab.label }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 人员信息标题 -->
|
||||||
|
<view class="section-title">人员信息</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 人员列表 - 独立滚动区域 -->
|
||||||
|
<scroll-view class="staff-scroll" scroll-y :style="{ height: scrollHeight + 'px' }">
|
||||||
|
<view class="staff-list">
|
||||||
|
<!-- 员工卡片 -->
|
||||||
|
<view
|
||||||
|
class="staff-item"
|
||||||
|
v-for="(item, index) in filteredStaffList"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<!-- 头像 -->
|
||||||
|
<image class="staff-avatar" :src="item.avatar" mode="aspectFill" />
|
||||||
|
|
||||||
|
<!-- 信息区 -->
|
||||||
|
<view class="staff-info">
|
||||||
|
<!-- 姓名+职业 -->
|
||||||
|
<view class="name-row">
|
||||||
|
<text class="name-label">姓名:</text>
|
||||||
|
<text class="name-text">{{ item.name }}</text>
|
||||||
|
<text class="job-label">职业:</text>
|
||||||
|
<text class="job-text">{{ item.job }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 电话 -->
|
||||||
|
<view class="phone-row">
|
||||||
|
<text class="phone-label">电话:</text>
|
||||||
|
<text class="phone-text">{{ item.phone }}</text>
|
||||||
|
<view class="call-btn" @tap="callPhone(item.phone)">
|
||||||
|
<text class="sicon-phone call-icon"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 职责描述 -->
|
||||||
|
<view class="duty-row">
|
||||||
|
<text class="duty-label">职责:</text>
|
||||||
|
<text class="duty-text">{{ item.duty }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-if="filteredStaffList.length === 0">
|
||||||
|
<text class="empty-text">暂无相关人员</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, onMounted, nextTick, getCurrentInstance } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
|
||||||
|
// 当前选中的分类Tab
|
||||||
|
const currentTab = ref('security');
|
||||||
|
|
||||||
|
// 列表滚动高度
|
||||||
|
const scrollHeight = ref(0);
|
||||||
|
|
||||||
|
// Tab列表
|
||||||
|
const tabList = ref([
|
||||||
|
{ key: 'security', label: '安保类' },
|
||||||
|
{ key: 'cleaning', label: '保洁类' },
|
||||||
|
{ key: 'engineering', label: '工程类' },
|
||||||
|
{ key: 'admin', label: '行政管理类' },
|
||||||
|
{ key: 'finance', label: '财务类' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 统计信息
|
||||||
|
const statsInfo = ref({
|
||||||
|
buildingName: '融侨馨苑',
|
||||||
|
total: 48,
|
||||||
|
categories: [
|
||||||
|
{ name: '安保', count: 10 },
|
||||||
|
{ name: '保洁', count: 10 },
|
||||||
|
{ name: '维修', count: 10 },
|
||||||
|
{ name: '楼管', count: 10 },
|
||||||
|
{ name: '经理', count: 2 },
|
||||||
|
{ name: '客服', count: 10 }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 人员列表数据
|
||||||
|
const staffList = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
category: 'security',
|
||||||
|
name: '吴仁贵',
|
||||||
|
job: '安保主管',
|
||||||
|
phone: '184****5263',
|
||||||
|
duty: '人员调配与排班、根据项目需求制定安保人员排班计划,确保24小时无缝覆盖。',
|
||||||
|
avatar: '/static/img/guest.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
category: 'security',
|
||||||
|
name: '李梓发',
|
||||||
|
job: '保安',
|
||||||
|
phone: '187****1005',
|
||||||
|
duty: '定期巡查项目重点区域,检查安全设施(监控、消防器材、门禁系统)是否完好',
|
||||||
|
avatar: '/static/img/login_img.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
category: 'security',
|
||||||
|
name: '冯启彬',
|
||||||
|
job: '保安',
|
||||||
|
phone: '187****1005',
|
||||||
|
duty: '定期巡查项目重点区域,检查安全设施(监控、消防器材、门禁系统)是否完好',
|
||||||
|
avatar: '/static/img/guest.png'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 根据当前Tab筛选列表
|
||||||
|
const filteredStaffList = computed(() => {
|
||||||
|
return staffList.value.filter(item => item.category === currentTab.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad(() => {
|
||||||
|
loadStaffData();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 渲染完成后计算scroll-view高度
|
||||||
|
onMounted(() => {
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
nextTick(() => {
|
||||||
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(instance)
|
||||||
|
.select('.page-header')
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
if (rect) {
|
||||||
|
// scroll-view高度 = 屏幕可用高度 - 头部高度 - 头部距顶部距离
|
||||||
|
scrollHeight.value = sysInfo.windowHeight - rect.height - rect.top;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载人员数据(TODO: 对接API)
|
||||||
|
function loadStaffData() {
|
||||||
|
// TODO: 调用API获取物业人员列表
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拨打电话
|
||||||
|
function callPhone(phone) {
|
||||||
|
uni.makePhoneCall({
|
||||||
|
phoneNumber: phone.replace(/\*/g, '') // 去掉脱敏星号
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* ==================== 页面容器 ==================== */
|
||||||
|
.staff-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 {
|
||||||
|
padding-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== 统计卡片 ==================== */
|
||||||
|
.stats-card {
|
||||||
|
margin: 24rpx 32rpx 24rpx;
|
||||||
|
padding: 28rpx 32rpx 24rpx;
|
||||||
|
background: linear-gradient(135deg, #EBF4FF 0%, #D6E7FF 100%);
|
||||||
|
border-radius: 24rpx;
|
||||||
|
|
||||||
|
/* 卡片顶部:小区名+标签 */
|
||||||
|
.card-top {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 小区信息 */
|
||||||
|
.building-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.building-icon {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-right: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building-name {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 物业人员标签 */
|
||||||
|
.staff-badge {
|
||||||
|
background: linear-gradient(135deg, #5B9BFF 0%, #3D7BD9 100%);
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 8rpx 24rpx;
|
||||||
|
border-radius: 24rpx 0 24rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 总人数行 */
|
||||||
|
.total-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
|
||||||
|
.total-label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666666;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-count {
|
||||||
|
font-size: 48rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FA7E49; /* 橙色主题 */
|
||||||
|
|
||||||
|
.total-unit {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FA7E49;
|
||||||
|
margin-left: 4rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分类统计行 */
|
||||||
|
.category-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.category-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.cat-name {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666666;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cat-count {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== 分类Tab栏 ==================== */
|
||||||
|
.tab-scroll {
|
||||||
|
white-space: nowrap;
|
||||||
|
margin: 0 0 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar {
|
||||||
|
display: inline-flex;
|
||||||
|
padding: 0 32rpx;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
margin-right: 40rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选中状态 */
|
||||||
|
&.active {
|
||||||
|
.tab-text {
|
||||||
|
color: #FA7E49; /* 橙色主题 */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部橙色指示条 */
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 48rpx;
|
||||||
|
height: 4rpx;
|
||||||
|
background: #FA7E49;
|
||||||
|
border-radius: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== 人员信息标题 ==================== */
|
||||||
|
.section-title {
|
||||||
|
padding: 16rpx 32rpx 20rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== 人员列表滚动区域 ==================== */
|
||||||
|
.staff-scroll {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== 人员列表内容 ==================== */
|
||||||
|
.staff-list {
|
||||||
|
padding: 0 32rpx 160rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== 单个员工卡片 ==================== */
|
||||||
|
.staff-item {
|
||||||
|
display: flex;
|
||||||
|
padding: 28rpx 0;
|
||||||
|
|
||||||
|
/* 分割线(非第一项) */
|
||||||
|
&:not(:last-child)::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 112rpx;
|
||||||
|
right: 0;
|
||||||
|
height: 1rpx;
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 头像 */
|
||||||
|
.staff-avatar {
|
||||||
|
width: 96rpx;
|
||||||
|
height: 96rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 信息区域 */
|
||||||
|
.staff-info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 24rpx;
|
||||||
|
|
||||||
|
/* 姓名+职业行 */
|
||||||
|
.name-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
|
||||||
|
.name-label,
|
||||||
|
.job-label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-text,
|
||||||
|
.job-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 电话行 */
|
||||||
|
.phone-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
|
||||||
|
.phone-label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 拨打按钮 */
|
||||||
|
.call-btn {
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #FA7E49;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.call-icon {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 职责描述行 */
|
||||||
|
.duty-row {
|
||||||
|
.duty-label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duty-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666666;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== 空状态 ==================== */
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 200rpx 0;
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M20 21a8 8 0 1 0-16 0"/></svg>
|
||||||
|
After Width: | Height: | Size: 222 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#333333" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
|
||||||
|
After Width: | Height: | Size: 285 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></svg>
|
||||||
|
After Width: | Height: | Size: 247 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
|
||||||
|
After Width: | Height: | Size: 218 B |
Loading…
Reference in New Issue