feat(home): 动态加载首页数据并新增详情页
parent
1582d6e193
commit
bd1c6a9596
1
.env
1
.env
|
|
@ -7,6 +7,7 @@ SHOPRO_BASE_URL=http://api-dashboard.yudao.iocoder.cn
|
||||||
# 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
|
# 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
|
||||||
#SHOPRO_DEV_BASE_URL=http://127.0.0.1:48080
|
#SHOPRO_DEV_BASE_URL=http://127.0.0.1:48080
|
||||||
SHOPRO_DEV_BASE_URL=http://1.12.53.43:9999
|
SHOPRO_DEV_BASE_URL=http://1.12.53.43:9999
|
||||||
|
#SHOPRO_DEV_BASE_URL=http://192.168.1.105:48080
|
||||||
### SHOPRO_DEV_BASE_URL=http://10.171.1.188:48080
|
### SHOPRO_DEV_BASE_URL=http://10.171.1.188:48080
|
||||||
### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
|
### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
|
||||||
|
|
||||||
|
|
|
||||||
46
pages.json
46
pages.json
|
|
@ -605,7 +605,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "notice/detail",
|
"path": "community/dynamics-detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "社区动态"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "社区动态详情",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "notice/list",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "通知公告"
|
"navigationBarTitleText": "通知公告"
|
||||||
},
|
},
|
||||||
|
|
@ -615,6 +626,17 @@
|
||||||
"group": "物业管理"
|
"group": "物业管理"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "notice/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "通知详情"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "通知详情",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "activity/list",
|
"path": "activity/list",
|
||||||
"style": {
|
"style": {
|
||||||
|
|
@ -670,6 +692,17 @@
|
||||||
"group": "物业管理"
|
"group": "物业管理"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "knowledge/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "知识课堂"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "知识课堂详情",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "community/daily",
|
"path": "community/daily",
|
||||||
"style": {
|
"style": {
|
||||||
|
|
@ -681,6 +714,17 @@
|
||||||
"title": "物业日常",
|
"title": "物业日常",
|
||||||
"group": "物业管理"
|
"group": "物业管理"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "service/more",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "更多服务"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "更多服务",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
indicator-color="rgba(255, 127, 105, 0.3)"
|
indicator-color="rgba(255, 127, 105, 0.3)"
|
||||||
indicator-active-color="#FF7F69"
|
indicator-active-color="#FF7F69"
|
||||||
>
|
>
|
||||||
<swiper-item v-for="(item, index) in bannerList" :key="index">
|
<swiper-item v-for="(item, index) in bannerList" :key="index" @tap="handleBannerTap(item)">
|
||||||
<view class="banner-content">
|
<view class="banner-content">
|
||||||
<view class="banner-text">
|
<view class="banner-text">
|
||||||
<text class="banner-title">{{ item.title }}</text>
|
<text class="banner-title">{{ item.title }}</text>
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
<!-- 通知栏 -->
|
<!-- 通知栏 -->
|
||||||
<view class="notice-bar" @tap="goNotice">
|
<view class="notice-bar" @tap="goNotice">
|
||||||
<view class="notice-tag">通知</view>
|
<view class="notice-tag">通知</view>
|
||||||
<text class="notice-text">关于做好小区消防安全管理的通知...</text>
|
<text class="notice-text">{{ noticeTitle || '暂无通知' }}</text>
|
||||||
<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>
|
||||||
|
|
||||||
|
|
@ -111,6 +111,7 @@
|
||||||
import { ref, onMounted, computed } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
import MemberHouseApi from '@/sheep/api/community/memberHouse';
|
import MemberHouseApi from '@/sheep/api/community/memberHouse';
|
||||||
|
import NoticeApi from '@/sheep/api/community/notice';
|
||||||
import sheep from '@/sheep';
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
// 状态栏高度
|
// 状态栏高度
|
||||||
|
|
@ -145,22 +146,37 @@ const houseAddress = computed(() => {
|
||||||
return userInfo.value.currentHouseAddress || '';
|
return userInfo.value.currentHouseAddress || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
// Banner轮播数据
|
// 通知数据
|
||||||
const bannerList = ref([
|
const noticeTitle = ref('');
|
||||||
{
|
|
||||||
title: '智慧社区',
|
|
||||||
subtitle: '让生活更简单',
|
|
||||||
icon: '/static/img/home-banner-icon.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '智慧社区',
|
|
||||||
subtitle: '让生活更简单',
|
|
||||||
icon: '/static/img/home-banner-icon.png',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 功能入口列表
|
// 查询最新通知
|
||||||
const functionList = ref([
|
const fetchNotice = async () => {
|
||||||
|
const { code, data } = await NoticeApi.getPage({ pageNo: 1, pageSize: 1 });
|
||||||
|
if (code === 0 && data && data.list && data.list.length > 0) {
|
||||||
|
noticeTitle.value = data.list[0].title;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Banner轮播数据
|
||||||
|
const bannerList = ref([]);
|
||||||
|
|
||||||
|
// 查询Banner列表
|
||||||
|
const fetchBannerList = async () => {
|
||||||
|
const { code, data } = await NoticeApi.getBannerList(1);
|
||||||
|
if (code === 0 && data && data.length > 0) {
|
||||||
|
bannerList.value = data.map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.name,
|
||||||
|
subtitle: '',
|
||||||
|
icon: item.picUrl,
|
||||||
|
url: item.url,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 功能入口列表(静态配置已注释,改为接口动态获取)
|
||||||
|
/*
|
||||||
|
const functionListStatic = [
|
||||||
{ 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_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: '/pages/sub/community/daily' },
|
{ 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: '/pages/sub/income/index' },
|
{ label: '收益公示', icon: '/static/img/Group_3.png', bgGradient: 'linear-gradient(35deg, #FFA940 0%, #FA8C16 100%)', path: '/pages/sub/income/index' },
|
||||||
|
|
@ -169,7 +185,34 @@ const functionList = ref([
|
||||||
{ 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_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: '' },
|
||||||
]);
|
];
|
||||||
|
*/
|
||||||
|
const functionList = ref([]);
|
||||||
|
|
||||||
|
// 功能入口背景色预设(按索引循环使用)
|
||||||
|
const bgGradientPresets = [
|
||||||
|
'linear-gradient(35deg, #FF7F69 0%, #FC5A5D 100%)',
|
||||||
|
'linear-gradient(35deg, #52C41A 0%, #36AD1A 100%)',
|
||||||
|
'linear-gradient(35deg, #FFA940 0%, #FA8C16 100%)',
|
||||||
|
'linear-gradient(35deg, #4096FF 0%, #1890FF 100%)',
|
||||||
|
'linear-gradient(35deg, #69B1FF 0%, #4096FF 100%)',
|
||||||
|
'linear-gradient(35deg, #9254DE 0%, #722ED1 100%)',
|
||||||
|
'linear-gradient(35deg, #7B61FF 0%, #597EF7 100%)',
|
||||||
|
'linear-gradient(35deg, #36CFC9 0%, #13C2C2 100%)',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 查询功能入口列表
|
||||||
|
const fetchFunctionList = async () => {
|
||||||
|
const { code, data } = await NoticeApi.getMiniAppConfigList(1);
|
||||||
|
if (code === 0 && data && data.length > 0) {
|
||||||
|
functionList.value = data.map((item, index) => ({
|
||||||
|
label: item.name,
|
||||||
|
icon: item.icon,
|
||||||
|
path: item.url,
|
||||||
|
bgGradient: bgGradientPresets[index % bgGradientPresets.length],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
// 获取状态栏高度
|
// 获取状态栏高度
|
||||||
|
|
@ -177,6 +220,12 @@ onLoad(() => {
|
||||||
statusBarHeight.value = systemInfo.statusBarHeight || 0;
|
statusBarHeight.value = systemInfo.statusBarHeight || 0;
|
||||||
// 加载小区房屋树
|
// 加载小区房屋树
|
||||||
fetchCommunityTree();
|
fetchCommunityTree();
|
||||||
|
// 加载最新通知
|
||||||
|
fetchNotice();
|
||||||
|
// 加载Banner
|
||||||
|
fetchBannerList();
|
||||||
|
// 加载功能入口
|
||||||
|
fetchFunctionList();
|
||||||
});
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
|
@ -239,8 +288,9 @@ const showCommunityPicker = () => {
|
||||||
|
|
||||||
// 功能入口点击
|
// 功能入口点击
|
||||||
const handleFunctionTap = (item) => {
|
const handleFunctionTap = (item) => {
|
||||||
if (item.path) {
|
const path = item.path ? item.path.trim() : '';
|
||||||
uni.navigateTo({ url: item.path });
|
if (path && path !== '/') {
|
||||||
|
uni.navigateTo({ url: path });
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: `${item.label}功能开发中`, icon: 'none' });
|
uni.showToast({ title: `${item.label}功能开发中`, icon: 'none' });
|
||||||
}
|
}
|
||||||
|
|
@ -248,7 +298,7 @@ const handleFunctionTap = (item) => {
|
||||||
|
|
||||||
// 通知
|
// 通知
|
||||||
const goNotice = () => {
|
const goNotice = () => {
|
||||||
uni.navigateTo({ url: '/pages/sub/notice/detail?id=1' });
|
uni.navigateTo({ url: '/pages/sub/notice/list' });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转登录页
|
// 跳转登录页
|
||||||
|
|
@ -285,6 +335,18 @@ const goActivityList = () => {
|
||||||
const goActivityDetail = () => {
|
const goActivityDetail = () => {
|
||||||
uni.navigateTo({ url: '/pages/sub/activity/detail?id=1' });
|
uni.navigateTo({ url: '/pages/sub/activity/detail?id=1' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Banner点击跳转
|
||||||
|
const handleBannerTap = (item) => {
|
||||||
|
if (!item.url) return;
|
||||||
|
// 外部链接用webview打开
|
||||||
|
if (item.url.startsWith('http')) {
|
||||||
|
uni.navigateTo({ url: `/pages/public/webview?url=${encodeURIComponent(item.url)}` });
|
||||||
|
} else {
|
||||||
|
// 内部页面直接跳转
|
||||||
|
uni.navigateTo({ url: item.url });
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
<input
|
<input
|
||||||
class="form-input"
|
class="form-input"
|
||||||
type="number"
|
type="number"
|
||||||
maxlength="4"
|
|
||||||
placeholder="请输入验证码"
|
placeholder="请输入验证码"
|
||||||
placeholder-class="input-placeholder"
|
placeholder-class="input-placeholder"
|
||||||
v-model="formData.code"
|
v-model="formData.code"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,210 @@
|
||||||
|
<!-- 社区动态详情页 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="社区动态" navbar="inner" color="#333333">
|
||||||
|
<!-- 渐变背景 -->
|
||||||
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
|
<!-- 固定头部区域(标题+发布信息) -->
|
||||||
|
<view class="detail-header">
|
||||||
|
<view class="header-inner">
|
||||||
|
<!-- 标题 -->
|
||||||
|
<view class="detail-title">
|
||||||
|
<text class="title-text">{{ detailInfo.title }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 发布信息 -->
|
||||||
|
<view class="publish-info">
|
||||||
|
<text class="community-name">{{ detailInfo.communityName }}</text>
|
||||||
|
<text class="publish-date">{{ detailInfo.publishDate ? sheep.$helper.timeFormat(detailInfo.publishDate, 'yyyy年mm月dd日 hh:MM') : '' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<view class="divider"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 富文本内容 - 固定滚动区域 -->
|
||||||
|
<scroll-view class="content-scroll" scroll-y :style="{ height: scrollHeight + 'px', top: scrollTop + 'px' }">
|
||||||
|
<view class="content-card">
|
||||||
|
<view class="content-inner">
|
||||||
|
<mp-html :content="detailInfo.content"></mp-html>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 底部占位 -->
|
||||||
|
<view class="bottom-placeholder"></view>
|
||||||
|
</scroll-view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import DynamicsApi from '@/sheep/api/community/dynamics';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
|
// 详情数据
|
||||||
|
const detailInfo = ref({
|
||||||
|
title: '',
|
||||||
|
communityName: '',
|
||||||
|
publishDate: '',
|
||||||
|
content: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 滚动区域高度
|
||||||
|
const scrollHeight = ref(0);
|
||||||
|
// 滚动区域距离顶部距离
|
||||||
|
const scrollTop = ref(0);
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.id) {
|
||||||
|
loadDetail(options.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算scroll-view高度和位置
|
||||||
|
const calcScrollHeight = () => {
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
nextTick(() => {
|
||||||
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
const query = uni.createSelectorQuery().in(instance);
|
||||||
|
|
||||||
|
// 获取头部区域高度和位置
|
||||||
|
query.select('.detail-header').boundingClientRect();
|
||||||
|
query.exec((res) => {
|
||||||
|
const headerRect = res[0];
|
||||||
|
if (headerRect) {
|
||||||
|
const safeBottom = sysInfo.safeAreaInsets?.bottom || 0;
|
||||||
|
scrollTop.value = headerRect.height + headerRect.top;
|
||||||
|
scrollHeight.value = sysInfo.windowHeight - scrollTop.value - safeBottom;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
calcScrollHeight();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载详情
|
||||||
|
async function loadDetail(id) {
|
||||||
|
const { code, data } = await DynamicsApi.getDetail(id);
|
||||||
|
if (code === 0 && data) {
|
||||||
|
const communityName = data.author || '';
|
||||||
|
|
||||||
|
detailInfo.value = {
|
||||||
|
title: data.title || '',
|
||||||
|
communityName,
|
||||||
|
publishDate: data.publishTime || '',
|
||||||
|
content: data.content || '',
|
||||||
|
};
|
||||||
|
|
||||||
|
setTimeout(calcScrollHeight, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 固定头部区域 */
|
||||||
|
.detail-header {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 10;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-inner {
|
||||||
|
padding: 0 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 文章标题 */
|
||||||
|
.detail-title {
|
||||||
|
padding: 32rpx 0 24rpx;
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 发布信息 */
|
||||||
|
.publish-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
padding-bottom: 24rpx;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
|
||||||
|
.community-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666666;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.publish-date {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分割线 */
|
||||||
|
.divider {
|
||||||
|
height: 1rpx;
|
||||||
|
background-color: #E5E5E5;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容滚动区域 - 固定定位 */
|
||||||
|
.content-scroll {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容卡片 */
|
||||||
|
.content-card {
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 富文本内容 */
|
||||||
|
.content-inner {
|
||||||
|
:deep(p) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(img) {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
margin: 16rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部占位 */
|
||||||
|
.bottom-placeholder {
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
<view class="item-content">
|
<view class="item-content">
|
||||||
<text class="item-title">{{ item.title }}</text>
|
<text class="item-title">{{ item.title }}</text>
|
||||||
<view class="item-footer">
|
<view class="item-footer">
|
||||||
<text class="item-views">{{ item.views }}</text>
|
<text class="item-views">{{ item.views||0 }}人浏览</text>
|
||||||
<text class="item-date">{{ item.date }}</text>
|
<text class="item-date">{{ item.date }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -52,8 +52,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
import { ref, onMounted, nextTick, getCurrentInstance, computed } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import DynamicsApi from '@/sheep/api/community/dynamics';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
// 列表滚动区域高度(单位:px),通过JS计算后绑定到scroll-view
|
// 列表滚动区域高度(单位:px),通过JS计算后绑定到scroll-view
|
||||||
const scrollViewHeight = ref(0);
|
const scrollViewHeight = ref(0);
|
||||||
|
|
@ -63,57 +65,36 @@ const tabList = ref(['全部', '物业', '业委会', '社区']);
|
||||||
const currentTab = ref(0);
|
const currentTab = ref(0);
|
||||||
|
|
||||||
// 动态列表
|
// 动态列表
|
||||||
const dynamicsList = ref([
|
const dynamicsList = ref([]);
|
||||||
{
|
|
||||||
id: 1,
|
// 分页参数
|
||||||
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
const pageNo = ref(1);
|
||||||
cover: '/static/img/guest.png',
|
const pageSize = ref(10);
|
||||||
views: '1.2万播放',
|
const total = ref(0);
|
||||||
date: '2021/02/21'
|
const loading = ref(false);
|
||||||
},
|
const noMore = ref(false);
|
||||||
{
|
|
||||||
id: 2,
|
// 当前小区ID
|
||||||
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
const communityId = computed(() => {
|
||||||
cover: '/static/img/guest.png',
|
return sheep.$store('user').userInfo?.currentCommunityId || null;
|
||||||
views: '1.2万播放',
|
});
|
||||||
date: '2021/02/21'
|
|
||||||
},
|
// Tab 类型映射
|
||||||
{
|
const tabTypeMap = {
|
||||||
id: 3,
|
0: null, // 全部
|
||||||
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
1: 1, // 物业
|
||||||
cover: '/static/img/guest.png',
|
2: 2, // 业委会
|
||||||
views: '1.2万播放',
|
3: 3, // 社区
|
||||||
date: '2021/02/21'
|
};
|
||||||
},
|
|
||||||
{
|
// 格式化浏览量
|
||||||
id: 4,
|
function formatViewCount(count) {
|
||||||
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
if (!count && count !== 0) return '0';
|
||||||
cover: '/static/img/guest.png',
|
if (count >= 10000) {
|
||||||
views: '1.2万播放',
|
return (count / 10000).toFixed(1) + '万';
|
||||||
date: '2021/02/21'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
|
||||||
cover: '/static/img/guest.png',
|
|
||||||
views: '1.2万播放',
|
|
||||||
date: '2021/02/21'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
|
||||||
cover: '/static/img/guest.png',
|
|
||||||
views: '1.2万播放',
|
|
||||||
date: '2021/02/21'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
title: '社区动态标题xxxx操作手册--如何邀请访客',
|
|
||||||
cover: '/static/img/guest.png',
|
|
||||||
views: '1.2万播放',
|
|
||||||
date: '2021/02/21'
|
|
||||||
}
|
}
|
||||||
]);
|
return String(count);
|
||||||
|
}
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
|
|
@ -145,12 +126,57 @@ onMounted(() => {
|
||||||
// 切换 Tab
|
// 切换 Tab
|
||||||
function switchTab(index) {
|
function switchTab(index) {
|
||||||
currentTab.value = index;
|
currentTab.value = index;
|
||||||
|
pageNo.value = 1;
|
||||||
|
noMore.value = false;
|
||||||
loadDynamicsList();
|
loadDynamicsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载动态列表
|
// 加载动态列表
|
||||||
async function loadDynamicsList() {
|
async function loadDynamicsList() {
|
||||||
// TODO: 调用API获取动态列表
|
if (loading.value) return;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
pageNo: pageNo.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
const postType = tabTypeMap[currentTab.value];
|
||||||
|
if (postType) {
|
||||||
|
params.postType = postType;
|
||||||
|
}
|
||||||
|
if (communityId.value) {
|
||||||
|
params.communityId = communityId.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { code, data } = await DynamicsApi.getPage(params);
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
if (code === 0 && data) {
|
||||||
|
const list = (data.list || []).map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
cover: item.coverImage || '/static/img/guest.png',
|
||||||
|
views: formatViewCount(item.viewCount),
|
||||||
|
date: item.publishTime ? sheep.$helper.timeFormat(item.publishTime, 'yyyy/mm/dd') : '',
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (pageNo.value === 1) {
|
||||||
|
dynamicsList.value = list;
|
||||||
|
} else {
|
||||||
|
dynamicsList.value = dynamicsList.value.concat(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
total.value = data.total || 0;
|
||||||
|
noMore.value = dynamicsList.value.length >= total.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多
|
||||||
|
function loadMore() {
|
||||||
|
if (noMore.value || loading.value) return;
|
||||||
|
pageNo.value += 1;
|
||||||
|
loadDynamicsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 跳转详情
|
// 跳转详情
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 列表区域 - 独立滚动区域 -->
|
<!-- 列表区域 - 独立滚动区域 -->
|
||||||
<scroll-view class="classroom-list" scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
<scroll-view class="classroom-list" scroll-y :style="{ height: scrollViewHeight + 'px' }" v-if="classroomList.length > 0">
|
||||||
<view class="list-inner" :class="{ 'grid-layout': currentTab === 1 }">
|
<view class="list-inner" :class="{ 'grid-layout': currentTab === 1 }">
|
||||||
<view
|
<view
|
||||||
class="classroom-item"
|
class="classroom-item"
|
||||||
|
|
@ -31,9 +31,6 @@
|
||||||
<!-- 封面图 -->
|
<!-- 封面图 -->
|
||||||
<view class="item-cover-wrap">
|
<view class="item-cover-wrap">
|
||||||
<image class="item-cover" :src="item.cover" mode="aspectFill" />
|
<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>
|
||||||
|
|
||||||
<!-- 内容区 -->
|
<!-- 内容区 -->
|
||||||
|
|
@ -54,20 +51,22 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 空状态 -->
|
|
||||||
<view class="empty-state" v-if="classroomList.length === 0">
|
|
||||||
<text class="empty-text">暂无数据</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-else>
|
||||||
|
<text class="empty-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</s-layout>
|
</s-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
import { ref, onMounted, nextTick, getCurrentInstance, computed } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import KnowledgeApi from '@/sheep/api/community/knowledge';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
// 列表滚动区域高度(单位:px),通过JS计算后绑定到scroll-view
|
// 列表滚动区域高度(单位:px),通过JS计算后绑定到scroll-view
|
||||||
const scrollViewHeight = ref(0);
|
const scrollViewHeight = ref(0);
|
||||||
|
|
@ -79,6 +78,33 @@ const currentTab = ref(0);
|
||||||
// 知识课堂列表
|
// 知识课堂列表
|
||||||
const classroomList = ref([]);
|
const classroomList = ref([]);
|
||||||
|
|
||||||
|
// 分页参数
|
||||||
|
const pageNo = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(0);
|
||||||
|
const loading = ref(false);
|
||||||
|
const noMore = ref(false);
|
||||||
|
|
||||||
|
// 当前小区ID
|
||||||
|
const communityId = computed(() => {
|
||||||
|
return sheep.$store('user').userInfo?.currentCommunityId || null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tab 类型映射
|
||||||
|
const tabTypeMap = {
|
||||||
|
0: 1, // 法律小课堂
|
||||||
|
1: 2, // 小区治理
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化数量
|
||||||
|
function formatCount(count) {
|
||||||
|
if (!count && count !== 0) return '0';
|
||||||
|
if (count >= 10000) {
|
||||||
|
return (count / 10000).toFixed(1) + '万';
|
||||||
|
}
|
||||||
|
return String(count);
|
||||||
|
}
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
if (options.tab) {
|
if (options.tab) {
|
||||||
|
|
@ -109,90 +135,60 @@ onMounted(() => {
|
||||||
// 切换 Tab
|
// 切换 Tab
|
||||||
function switchTab(index) {
|
function switchTab(index) {
|
||||||
currentTab.value = index;
|
currentTab.value = index;
|
||||||
|
pageNo.value = 1;
|
||||||
|
noMore.value = false;
|
||||||
loadClassroomList();
|
loadClassroomList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载知识课堂列表
|
// 加载知识课堂列表
|
||||||
async function loadClassroomList() {
|
async function loadClassroomList() {
|
||||||
// TODO: 调用API获取列表
|
if (loading.value) return;
|
||||||
// 模拟数据
|
loading.value = true;
|
||||||
if (currentTab.value === 0) {
|
|
||||||
// 法律小课堂 - 列表样式
|
const params = {
|
||||||
classroomList.value = [
|
pageNo: pageNo.value,
|
||||||
{
|
pageSize: pageSize.value,
|
||||||
id: 1,
|
};
|
||||||
title: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX法规解读',
|
|
||||||
cover: '/static/img/guest.png',
|
const classType = tabTypeMap[currentTab.value];
|
||||||
date: '2025/07/05 12:00'
|
if (classType) {
|
||||||
},
|
params.classType = classType;
|
||||||
{
|
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
];
|
if (communityId.value) {
|
||||||
|
params.communityId = communityId.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { code, data } = await KnowledgeApi.getPage(params);
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
if (code === 0 && data) {
|
||||||
|
const list = (data.list || []).map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
cover: item.coverImage || '/static/img/guest.png',
|
||||||
|
views: formatCount(item.viewCount),
|
||||||
|
likes: formatCount(item.likeCount),
|
||||||
|
date: item.createTime ? sheep.$helper.timeFormat(item.createTime, 'yyyy/mm/dd hh:MM') : '',
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (pageNo.value === 1) {
|
||||||
|
classroomList.value = list;
|
||||||
} else {
|
} else {
|
||||||
// 小区治理 - 网格样式
|
classroomList.value = classroomList.value.concat(list);
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
];
|
|
||||||
|
total.value = data.total || 0;
|
||||||
|
noMore.value = classroomList.value.length >= total.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载更多
|
||||||
|
function loadMore() {
|
||||||
|
if (noMore.value || loading.value) return;
|
||||||
|
pageNo.value += 1;
|
||||||
|
loadClassroomList();
|
||||||
|
}
|
||||||
|
|
||||||
// 跳转详情
|
// 跳转详情
|
||||||
function goDetail(item) {
|
function goDetail(item) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
<!-- 知识课堂详情页 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="知识课堂" navbar="inner" color="#333333">
|
||||||
|
<!-- 渐变背景 -->
|
||||||
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
|
<!-- 固定头部区域(标题+发布信息) -->
|
||||||
|
<view class="detail-header">
|
||||||
|
<view class="header-inner">
|
||||||
|
<!-- 标题 -->
|
||||||
|
<view class="detail-title">
|
||||||
|
<text class="title-text">{{ detailInfo.title }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 发布信息 -->
|
||||||
|
<view class="publish-info">
|
||||||
|
<text class="community-name">{{ detailInfo.viewCount || 0 }}次浏览</text>
|
||||||
|
<text class="publish-date">{{ detailInfo.publishDate ? sheep.$helper.timeFormat(detailInfo.publishDate, 'yyyy年mm月dd日 hh:MM') : '' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<view class="divider"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 富文本内容 - 固定滚动区域 -->
|
||||||
|
<scroll-view class="content-scroll" scroll-y :style="{ height: scrollHeight + 'px', top: scrollTop + 'px' }">
|
||||||
|
<view class="content-card">
|
||||||
|
<view class="content-inner">
|
||||||
|
<mp-html :content="detailInfo.content"></mp-html>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 底部占位 -->
|
||||||
|
<view class="bottom-placeholder"></view>
|
||||||
|
</scroll-view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import KnowledgeApi from '@/sheep/api/community/knowledge';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
|
// 详情数据
|
||||||
|
const detailInfo = ref({
|
||||||
|
title: '',
|
||||||
|
viewCount: '',
|
||||||
|
publishDate: '',
|
||||||
|
content: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 滚动区域高度
|
||||||
|
const scrollHeight = ref(0);
|
||||||
|
// 滚动区域距离顶部距离
|
||||||
|
const scrollTop = ref(0);
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.id) {
|
||||||
|
loadDetail(options.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算scroll-view高度和位置
|
||||||
|
const calcScrollHeight = () => {
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
nextTick(() => {
|
||||||
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
const query = uni.createSelectorQuery().in(instance);
|
||||||
|
|
||||||
|
// 获取头部区域高度和位置
|
||||||
|
query.select('.detail-header').boundingClientRect();
|
||||||
|
query.exec((res) => {
|
||||||
|
const headerRect = res[0];
|
||||||
|
if (headerRect) {
|
||||||
|
const safeBottom = sysInfo.safeAreaInsets?.bottom || 0;
|
||||||
|
scrollTop.value = headerRect.height + headerRect.top;
|
||||||
|
scrollHeight.value = sysInfo.windowHeight - scrollTop.value - safeBottom;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
calcScrollHeight();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载详情
|
||||||
|
async function loadDetail(id) {
|
||||||
|
const { code, data } = await KnowledgeApi.getDetail(id);
|
||||||
|
if (code === 0 && data) {
|
||||||
|
detailInfo.value = {
|
||||||
|
title: data.title || '',
|
||||||
|
viewCount: data.viewCount || '',
|
||||||
|
publishDate: data.createTime || '',
|
||||||
|
content: data.content || '',
|
||||||
|
};
|
||||||
|
|
||||||
|
setTimeout(calcScrollHeight, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 固定头部区域 */
|
||||||
|
.detail-header {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 10;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-inner {
|
||||||
|
padding: 0 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 文章标题 */
|
||||||
|
.detail-title {
|
||||||
|
padding: 32rpx 0 24rpx;
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 发布信息 */
|
||||||
|
.publish-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
padding-bottom: 24rpx;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.community-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666666;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.publish-date {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999999;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分割线 */
|
||||||
|
.divider {
|
||||||
|
height: 1rpx;
|
||||||
|
background-color: #E5E5E5;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容滚动区域 - 固定定位 */
|
||||||
|
.content-scroll {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容卡片 */
|
||||||
|
.content-card {
|
||||||
|
background-color: #FFF8F0;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
margin: 0 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 富文本内容 */
|
||||||
|
.content-inner {
|
||||||
|
:deep(p) {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(img) {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
margin: 16rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部占位 */
|
||||||
|
.bottom-placeholder {
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -15,10 +15,10 @@
|
||||||
<!-- 发布信息 -->
|
<!-- 发布信息 -->
|
||||||
<view class="publish-info">
|
<view class="publish-info">
|
||||||
<view class="publisher">
|
<view class="publisher">
|
||||||
<image class="publisher-avatar" src="/static/img/login_img.png" mode="aspectFill" />
|
<image class="publisher-avatar" src="/static/img/person.png" mode="aspectFill" />
|
||||||
<text class="publisher-name">{{ noticeInfo.publisher }}</text>
|
<text class="publisher-name">{{ noticeInfo.publisher }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="publish-date">{{ noticeInfo.publishDate }}</text>
|
<text class="publish-date">{{ noticeInfo.publishDate ? sheep.$helper.timeFormat(noticeInfo.publishDate, 'yyyy/mm/dd hh:MM:ss') : '' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 分割线 -->
|
<!-- 分割线 -->
|
||||||
|
|
@ -34,15 +34,15 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 占位,防止内容被底部附件遮挡 -->
|
<!-- 占位,防止内容被底部附件遮挡 -->
|
||||||
<view class="bottom-placeholder" v-if="noticeInfo.attachments && noticeInfo.attachments.length > 0"></view>
|
<view class="bottom-placeholder" v-if="noticeInfo.attachmentList && noticeInfo.attachmentList.length > 0"></view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<!-- 附件列表 - 固定在底部 -->
|
<!-- 附件列表 - 动态高度,随内容撑开 -->
|
||||||
<view class="attachment-section" v-if="noticeInfo.attachments && noticeInfo.attachments.length > 0">
|
<view class="attachment-section" v-if="noticeInfo.attachmentList && noticeInfo.attachmentList.length > 0">
|
||||||
<view class="attachment-inner">
|
<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.attachmentList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@tap="downloadAttachment(item)"
|
@tap="downloadAttachment(item)"
|
||||||
>
|
>
|
||||||
|
|
@ -58,8 +58,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
import { ref, onMounted, nextTick, getCurrentInstance, watch } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import NoticeApi from '@/sheep/api/community/notice';
|
||||||
import sheep from '@/sheep';
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
// 富文本滚动区域高度(单位:px)
|
// 富文本滚动区域高度(单位:px)
|
||||||
|
|
@ -73,7 +74,7 @@ const noticeInfo = ref({
|
||||||
publisher: '',
|
publisher: '',
|
||||||
publishDate: '',
|
publishDate: '',
|
||||||
content: '',
|
content: '',
|
||||||
attachments: []
|
attachmentList: []
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
|
|
@ -83,8 +84,8 @@ onLoad((options) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 渲染完成后计算scroll-view高度和位置
|
// 计算scroll-view高度和位置
|
||||||
onMounted(() => {
|
const calcScrollHeight = () => {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const sysInfo = uni.getSystemInfoSync();
|
const sysInfo = uni.getSystemInfoSync();
|
||||||
|
|
@ -107,55 +108,60 @@ onMounted(() => {
|
||||||
if (headerRect) {
|
if (headerRect) {
|
||||||
// scroll-view距离顶部 = 头部高度 + 头部距离顶部距离(已包含状态栏和导航栏高度)
|
// scroll-view距离顶部 = 头部高度 + 头部距离顶部距离(已包含状态栏和导航栏高度)
|
||||||
contentScrollTop.value = headerRect.height + headerRect.top;
|
contentScrollTop.value = headerRect.height + headerRect.top;
|
||||||
// scroll-view高度 = 屏幕可用高度 - scroll-view距离顶部 - 附件高度
|
// scroll-view高度 = 屏幕可用高度 - scroll-view距离顶部 - 附件高度 - 底部安全区
|
||||||
contentScrollHeight.value = sysInfo.windowHeight - contentScrollTop.value - attachmentHeight;
|
const safeBottom = sysInfo.safeAreaInsets?.bottom || 0;
|
||||||
|
contentScrollHeight.value = sysInfo.windowHeight - contentScrollTop.value - attachmentHeight - safeBottom;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染完成后计算
|
||||||
|
onMounted(() => {
|
||||||
|
calcScrollHeight();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 数据加载完成后重新计算(附件异步加载)
|
||||||
|
watch(() => noticeInfo.value.attachmentList, () => {
|
||||||
|
setTimeout(calcScrollHeight, 100);
|
||||||
|
}, { deep: true });
|
||||||
|
|
||||||
// 加载公告详情
|
// 加载公告详情
|
||||||
async function loadNoticeDetail(id) {
|
async function loadNoticeDetail(id) {
|
||||||
// TODO: 调用API获取公告详情
|
const { code, data } = await NoticeApi.getDetail(id);
|
||||||
// const { code, data } = await NoticeApi.getNoticeDetail(id);
|
if (code === 0 && data) {
|
||||||
// if (code === 0) {
|
|
||||||
// noticeInfo.value = data;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 模拟数据
|
|
||||||
noticeInfo.value = {
|
noticeInfo.value = {
|
||||||
title: '关于召开业主大会讨论物业费价格调整的通知',
|
title: data.title || '',
|
||||||
publisher: 'x小区物业',
|
publisher: data.publisher || '',
|
||||||
publishDate: '2026-01-20',
|
publishDate: data.publishTime || '',
|
||||||
content: `<p>各位业主:</p>
|
content: data.content || '',
|
||||||
<p>为进一步提升本小区物业服务质量,保障小区公共设施设备的正常运维、环境卫生整治、安保服务升级等工作有序开展,切实维护全体业主的共同利益,根据《物业管理条例》《业主大会和业主委员会指导规则》及本小区《管理规约》相关规定,经业主委员会研究决定,召开业主大会,专门讨论本小区物业费价格调整相关事宜。现将具体事项通知如下:</p>
|
attachmentList: (data.attachmentList || []).map((item) => ({
|
||||||
<p>一、会议基本信息</p>
|
name: item.name,
|
||||||
<p>会议时间:2026年2月15日(周六)上午9:00</p>
|
url: item.url,
|
||||||
<p>会议地点:小区活动中心一楼会议室</p>
|
type: getFileType(item.name),
|
||||||
<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: [
|
|
||||||
{ name: 'IMG-2309.PNG', type: 'image', url: '' },
|
|
||||||
{ name: 'EXCEL-2309.XLXS', type: 'excel', url: '' }
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
// 数据加载后重新计算scroll-view高度
|
||||||
|
setTimeout(calcScrollHeight, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据文件名判断文件类型
|
||||||
|
function getFileType(fileName) {
|
||||||
|
if (!fileName) return 'file';
|
||||||
|
const ext = fileName.split('.').pop().toLowerCase();
|
||||||
|
const typeMap = {
|
||||||
|
png: 'image',
|
||||||
|
jpg: 'image',
|
||||||
|
jpeg: 'image',
|
||||||
|
gif: 'image',
|
||||||
|
xls: 'excel',
|
||||||
|
xlsx: 'excel',
|
||||||
|
pdf: 'pdf',
|
||||||
|
doc: 'word',
|
||||||
|
docx: 'word',
|
||||||
|
};
|
||||||
|
return typeMap[ext] || 'file';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取附件图标
|
// 获取附件图标
|
||||||
|
|
@ -271,9 +277,9 @@ function downloadAttachment(item) {
|
||||||
padding: 0 32rpx;
|
padding: 0 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部占位 */
|
/* 底部占位 - 根据附件数量动态调整 */
|
||||||
.bottom-placeholder {
|
.bottom-placeholder {
|
||||||
height: 300rpx;
|
height: 40rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 文章标题 */
|
/* 文章标题 */
|
||||||
|
|
@ -302,7 +308,7 @@ function downloadAttachment(item) {
|
||||||
.publisher-avatar {
|
.publisher-avatar {
|
||||||
width: 48rpx;
|
width: 48rpx;
|
||||||
height: 48rpx;
|
height: 48rpx;
|
||||||
border-radius: 50%;
|
// border-radius: 50%;
|
||||||
margin-right: 16rpx;
|
margin-right: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -358,16 +364,16 @@ function downloadAttachment(item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 附件区域 - 固定在底部 */
|
/* 附件区域 - 动态高度,最多显示3个附件 */
|
||||||
.attachment-section {
|
.attachment-section {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 260rpx;
|
max-height: 360rpx;
|
||||||
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: 24rpx 24rpx 0 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
<!-- 通知公告列表 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="通知公告">
|
||||||
|
<view class="notice-list-page">
|
||||||
|
<scroll-view
|
||||||
|
class="notice-scroll"
|
||||||
|
scroll-y
|
||||||
|
:style="{ height: scrollHeight + 'px' }"
|
||||||
|
@scrolltolower="loadMore"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in state.list"
|
||||||
|
:key="index"
|
||||||
|
class="notice-card"
|
||||||
|
@tap="goDetail(item)"
|
||||||
|
>
|
||||||
|
<text class="notice-title">{{ item.title }}</text>
|
||||||
|
<view class="notice-content">
|
||||||
|
<mp-html :content="item.content" />
|
||||||
|
</view>
|
||||||
|
<view class="notice-footer">
|
||||||
|
<text class="notice-time">{{ sheep.$helper.timeFormat(item.publishTime, 'yyyy/mm/dd hh:MM:ss') }}</text>
|
||||||
|
<image class="arrow-icon" src="/static/img/right-icon.png" mode="aspectFit" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<view class="load-more">
|
||||||
|
<text v-if="state.loading">加载中...</text>
|
||||||
|
<text v-else-if="state.noMore">没有更多了</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||||
|
import NoticeApi from '@/sheep/api/community/notice';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
|
// scroll-view 动态高度
|
||||||
|
const scrollHeight = ref(0);
|
||||||
|
|
||||||
|
// 页面状态
|
||||||
|
const state = reactive({
|
||||||
|
list: [],
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
loading: false,
|
||||||
|
noMore: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取通知列表
|
||||||
|
const fetchList = async (isRefresh = false) => {
|
||||||
|
if (state.loading) return;
|
||||||
|
if (isRefresh) {
|
||||||
|
state.pageNo = 1;
|
||||||
|
state.noMore = false;
|
||||||
|
}
|
||||||
|
if (state.noMore && !isRefresh) return;
|
||||||
|
|
||||||
|
state.loading = true;
|
||||||
|
const { code, data } = await NoticeApi.getPage({
|
||||||
|
pageNo: state.pageNo,
|
||||||
|
pageSize: state.pageSize,
|
||||||
|
});
|
||||||
|
state.loading = false;
|
||||||
|
|
||||||
|
if (code === 0 && data) {
|
||||||
|
const list = data.list || [];
|
||||||
|
if (isRefresh) {
|
||||||
|
state.list = list;
|
||||||
|
} else {
|
||||||
|
state.list = state.list.concat(list);
|
||||||
|
}
|
||||||
|
// 判断是否还有更多
|
||||||
|
if (list.length < state.pageSize || state.list.length >= data.total) {
|
||||||
|
state.noMore = true;
|
||||||
|
}
|
||||||
|
state.pageNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRefresh) {
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载更多
|
||||||
|
const loadMore = () => {
|
||||||
|
fetchList(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 跳转详情
|
||||||
|
const goDetail = (item) => {
|
||||||
|
uni.navigateTo({ url: `/pages/sub/notice/detail?id=${item.id}` });
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
// 计算 scroll-view 可用高度
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
const safeBottom = sys.safeAreaInsets?.bottom || 0;
|
||||||
|
scrollHeight.value = sys.windowHeight - 88 - safeBottom;
|
||||||
|
fetchList(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
onPullDownRefresh(() => {
|
||||||
|
fetchList(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 页面容器 */
|
||||||
|
.notice-list-page {
|
||||||
|
height: 100%;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
padding: 24rpx 0 calc(24rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动区域 */
|
||||||
|
.notice-scroll {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 通知卡片 */
|
||||||
|
.notice-card {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
margin: 0 24rpx 24rpx;
|
||||||
|
padding: 28rpx 32rpx;
|
||||||
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-content {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666666;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
height: 90rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
:deep(p) {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666666;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(img) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.notice-time {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow-icon {
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载状态 */
|
||||||
|
.load-more {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 24rpx 0 40rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
<!-- 更多服务 - 模仿首页功能入口网格 -->
|
||||||
|
<template>
|
||||||
|
<view class="more-service-page">
|
||||||
|
<!-- 标题区 -->
|
||||||
|
<view class="page-header">
|
||||||
|
<text class="page-title">更多服务</text>
|
||||||
|
<text class="page-subtitle">可在此处查看所有服务哦~</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 功能入口网格 4列自适应 -->
|
||||||
|
<view class="service-grid" v-if="serviceList.length > 0">
|
||||||
|
<view
|
||||||
|
class="grid-item"
|
||||||
|
v-for="(item, index) in serviceList"
|
||||||
|
:key="index"
|
||||||
|
@tap="handleServiceTap(item)"
|
||||||
|
>
|
||||||
|
<view class="icon-wrapper" :style="{ background: item.bgGradient }">
|
||||||
|
<image class="icon-img" :src="item.icon" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<text class="icon-label">{{ item.label }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-else>
|
||||||
|
<text class="empty-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import NoticeApi from '@/sheep/api/community/notice';
|
||||||
|
|
||||||
|
// 服务列表
|
||||||
|
const serviceList = ref([]);
|
||||||
|
|
||||||
|
// 背景色预设(按索引循环使用)
|
||||||
|
const bgGradientPresets = [
|
||||||
|
'linear-gradient(35deg, #FF7F69 0%, #FC5A5D 100%)',
|
||||||
|
'linear-gradient(35deg, #52C41A 0%, #36AD1A 100%)',
|
||||||
|
'linear-gradient(35deg, #FFA940 0%, #FA8C16 100%)',
|
||||||
|
'linear-gradient(35deg, #4096FF 0%, #1890FF 100%)',
|
||||||
|
'linear-gradient(35deg, #69B1FF 0%, #4096FF 100%)',
|
||||||
|
'linear-gradient(35deg, #9254DE 0%, #722ED1 100%)',
|
||||||
|
'linear-gradient(35deg, #7B61FF 0%, #597EF7 100%)',
|
||||||
|
'linear-gradient(35deg, #36CFC9 0%, #13C2C2 100%)',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 查询服务列表(position=2)
|
||||||
|
const fetchServiceList = async () => {
|
||||||
|
const { code, data } = await NoticeApi.getMiniAppConfigList(2);
|
||||||
|
if (code === 0 && data && data.length > 0) {
|
||||||
|
serviceList.value = data.map((item, index) => ({
|
||||||
|
label: item.name,
|
||||||
|
icon: item.icon,
|
||||||
|
path: item.url,
|
||||||
|
bgGradient: bgGradientPresets[index % bgGradientPresets.length],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 服务点击
|
||||||
|
const handleServiceTap = (item) => {
|
||||||
|
const path = item.path ? item.path.trim() : '';
|
||||||
|
if (path && path !== '/') {
|
||||||
|
uni.navigateTo({ url: path });
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: `${item.label}功能开发中`, icon: 'none' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
fetchServiceList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.more-service-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
padding: 24rpx;
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-subtitle {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-grid {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 32rpx 16rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.grid-item {
|
||||||
|
width: 25%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
|
||||||
|
.icon-wrapper {
|
||||||
|
width: 88rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
border-radius: 34rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
|
||||||
|
.icon-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 120rpx 0;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
font-family: 'PingFang SC', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import request from '@/sheep/request';
|
||||||
|
|
||||||
|
const DynamicsApi = {
|
||||||
|
// 查询社区动态列表
|
||||||
|
getPage: (params) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/post/page',
|
||||||
|
method: 'GET',
|
||||||
|
data: params,
|
||||||
|
custom: {
|
||||||
|
showLoading: false,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 查询社区动态详情
|
||||||
|
getDetail: (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/post/get',
|
||||||
|
method: 'GET',
|
||||||
|
data: { id },
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DynamicsApi;
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import request from '@/sheep/request';
|
||||||
|
|
||||||
|
const KnowledgeApi = {
|
||||||
|
// 查询知识课堂列表
|
||||||
|
getPage: (params) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/knowledge-class/page',
|
||||||
|
method: 'GET',
|
||||||
|
data: params,
|
||||||
|
custom: {
|
||||||
|
showLoading: false,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 查询知识课堂详情
|
||||||
|
getDetail: (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/knowledge-class/get',
|
||||||
|
method: 'GET',
|
||||||
|
data: { id },
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KnowledgeApi;
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
import request from '@/sheep/request';
|
||||||
|
|
||||||
|
const NoticeApi = {
|
||||||
|
// 查询通知列表
|
||||||
|
getPage: (params) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/notice/page',
|
||||||
|
method: 'GET',
|
||||||
|
data: params,
|
||||||
|
custom: {
|
||||||
|
showLoading: false,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 查询通知详情
|
||||||
|
getDetail: (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/notice/get',
|
||||||
|
method: 'GET',
|
||||||
|
data: { id },
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 查询Banner列表
|
||||||
|
getBannerList: (position) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/banner/list',
|
||||||
|
method: 'GET',
|
||||||
|
data: { position },
|
||||||
|
custom: {
|
||||||
|
showLoading: false,
|
||||||
|
auth: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 查询小程序配置列表(功能入口)
|
||||||
|
getMiniAppConfigList: (position) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/mini-app-config/list',
|
||||||
|
method: 'GET',
|
||||||
|
data: { position },
|
||||||
|
custom: {
|
||||||
|
showLoading: false,
|
||||||
|
auth: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NoticeApi;
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Loading…
Reference in New Issue