优化界面

This commit is contained in:
Leo_Ding 2025-08-12 16:49:19 +08:00
parent 2a48964efb
commit 293b3d8bf3
6 changed files with 128 additions and 121 deletions

View File

@ -397,11 +397,11 @@ export default {
}, },
previewImage(index) { previewImage(index) {
if (!this.detailInfo.detailImages || !this.detailInfo.detailImages.length) return; // if (!this.detailInfo.detailImages || !this.detailInfo.detailImages.length) return;
uni.previewImage({ uni.previewImage({
current: index, current: index,
urls: this.detailInfo.detailImages.map(img => img.startsWith('http') ? img : IMAGE_BASE_URL + img) urls: this.detailInfo.imgs.map(img => img.startsWith('http') ? img : IMAGE_BASE_URL + img)
}); });
}, },

View File

@ -48,7 +48,7 @@
<view class="weather-main"> <view class="weather-main">
<view class="current-weather"> <view class="current-weather">
<image class="weather-icon" <image class="weather-icon"
:src="weather.weather ? getWeatherIcon(weather.weather) : '/static/imgs/weather/default.png'" :src="weather.weather ? getWeatherIcon(weather.weather) : '/static/imgs/weather.png'"
mode="aspectFit"></image> mode="aspectFit"></image>
<text class="current-temp">{{weather.real || '--'}}°</text> <text class="current-temp">{{weather.real || '--'}}°</text>
</view> </view>
@ -127,7 +127,7 @@ import Copyright from '@/components/gx-copyright.vue';
import Footer from '@/components/footer_common.vue'; import Footer from '@/components/footer_common.vue';
import { get, post } from '@/utils/request'; import { get, post } from '@/utils/request';
import { IMAGE_BASE_URL, BASE_URL } from '@/utils/config'; import { IMAGE_BASE_URL, BASE_URL } from '@/utils/config';
import {navigateTo} from '@/utils/router.js'
export default { export default {
components: { components: {
Footer, Footer,
@ -160,10 +160,15 @@ export default {
this.getWeather(); this.getWeather();
}, },
methods: { methods: {
goDetail(page) { goDetail(page) {
uni.navigateTo({ if(page==='neighbor'){
url: `/pages/${page}/index` navigateTo({url: `/pages/${page}/index`})
}); }else{
uni.navigateTo({
url: `/pages/${page}/index`
});
}
}, },
formatDate(date) { formatDate(date) {
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];

View File

@ -39,6 +39,7 @@
<!-- 预约记录列表 --> <!-- 预约记录列表 -->
<view class="order-list" v-else> <view class="order-list" v-else>
<u-loading-page :loading="dataloading"></u-loading-page>
<view v-if="orderList.length === 0" class="empty-container"> <view v-if="orderList.length === 0" class="empty-container">
<noData /> <noData />
</view> </view>
@ -313,6 +314,7 @@
// //
async getList() { async getList() {
try { try {
wx.showLoading({title:'加载中...',mask:true})
const res = await get('/api/v1/apps/home/metting-room', { const res = await get('/api/v1/apps/home/metting-room', {
current: 1, current: 1,
pageSize: 10, pageSize: 10,
@ -329,12 +331,13 @@
icon: 'none' icon: 'none'
}); });
} finally { } finally {
this.isLoading = false; wx.hideLoading()
} }
}, },
// //
async getOrderList() { async getOrderList() {
try { try {
wx.showLoading({title:'加载中...',mask:true})
const res = await get('/api/v1/app_auth/metting-room/order', { const res = await get('/api/v1/app_auth/metting-room/order', {
current: 1, current: 1,
pageSize: 10, pageSize: 10,
@ -352,7 +355,7 @@
icon: 'none' icon: 'none'
}); });
} finally { } finally {
this.isLoading = false; wx.hideLoading()
} }
}, },

View File

@ -52,11 +52,11 @@
height="780px" height="780px"
v-if="filteredOrders.length === 0" v-if="filteredOrders.length === 0"
mode="data" mode="data"
icon="/static/imgs/noData.jpeg" icon="/static/imgs/noData.png"
></u-empty> ></u-empty>
</view> </view>
</view> </view>
<Footer></Footer> <!-- <Footer></Footer> -->
<!-- 固定在右侧的发布工单按钮 --> <!-- 固定在右侧的发布工单按钮 -->
<view class="fab-container"> <view class="fab-container">

View File

@ -16,57 +16,58 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 实际列表 --> <!-- 滚动区域 -->
<view class="notice-item" <scroll-view scroll-y :style="'height:' + scrollViewHeight + 'px'" @scrolltolower="loadMore"
v-for="(item,index) in noticesList" lower-threshold="100" :scroll-with-animation="true">
:key="item.id" <view class="notice-item" v-for="(item,index) in noticesList" :key="item.id"
@click="goNoticeDetail(item.id)"> @click="goNoticeDetail(item.id)">
<image :src="item.cover" <image :src="item.cover" class="notice-image" mode="aspectFill" lazy-load
class="notice-image" :show-menu-by-longpress="true" @error="handleImageError(index)"></image>
mode="aspectFill" <view class="notice-content">
lazy-load <view class="notice-title line-clamp-1">{{item.title}}</view>
:show-menu-by-longpress="true" <view class="notice-description line-clamp-2" v-html="item.desc"></view>
@error="handleImageError(index)"></image> <view class="notice-footer">
<view class="notice-content"> <text class="notice-date">{{formatTime(item.createdAt,'YYYY-MM-DD')}}</text>
<view class="notice-title line-clamp-1">{{item.title}}</view> <text class="notice-more">查看详情 </text>
<view class="notice-description line-clamp-2" v-html="item.desc"></view> </view>
<view class="notice-footer">
<text class="notice-date">{{formatTime(item.createdAt,'YYYY-MM-DD')}}</text>
<text class="notice-more">查看详情 </text>
</view> </view>
</view> </view>
</view>
<!-- 加载更多提示 -->
<!-- 加载更多提示 --> <view class="load-more" v-if="noticesList.length > 0 && currentPage < totalPages">
<view class="load-more" v-if="noticesList.length > 0 && currentPage < totalPages"> <text>{{isLoading ? '加载中...' : '上拉加载更多'}}</text>
<text>{{isLoading ? '加载中...' : '上拉加载更多'}}</text> </view>
</view> </scroll-view>
<!-- 空状态 --> <!-- 空状态 -->
<view class="empty-state" v-if="noticesList.length === 0 && !isLoading"> <view class="empty-state" v-if="noticesList.length === 0 && !isLoading">
<image src="/static/images/empty-notice.png" class="empty-image"></image> <image src="/static/imgs/noData.png" class="empty-image"></image>
<text class="empty-text">暂无公告</text> <text class="empty-text">暂无公告</text>
</view> </view>
</view> </view>
</view> </view>
<Copyright/> <Copyright />
</view> </view>
<!-- 底部导航 -->
<Footer></Footer>
</view> </view>
</template> </template>
<script> <script>
import { get } from '@/utils/request'; import {
import { IMAGE_BASE_URL } from '@/utils/config'; get
import { formatTime } from '@/utils/timeFormat'; } from '@/utils/request';
import Footer from '@/components/footer_common.vue'; import {
IMAGE_BASE_URL
} from '@/utils/config';
import {
formatTime
} from '@/utils/timeFormat';
import Copyright from '@/components/gx-copyright.vue'; import Copyright from '@/components/gx-copyright.vue';
export default { export default {
components: { Footer,Copyright }, components: {
Copyright
},
data() { data() {
return { return {
formatTime, formatTime,
@ -76,23 +77,33 @@
isLoading: false, isLoading: false,
currentPage: 1, currentPage: 1,
totalPages: 1, totalPages: 1,
lastRequestTime: 0 lastRequestTime: 0,
scrollViewHeight: 500 // mounted
}; };
}, },
mounted() { mounted() {
this.calculateScrollHeight();
this.getNotices(); this.getNotices();
this.initScrollListener();
},
beforeDestroy() {
this.removeScrollListener();
}, },
methods: { methods: {
//
calculateScrollHeight() {
const systemInfo = uni.getSystemInfoSync();
const query = uni.createSelectorQuery().in(this);
query.select('.container').boundingClientRect(data => {
if (data) {
//
this.scrollViewHeight = systemInfo.windowHeight - 50;
}
}).exec();
},
async getNotices() { async getNotices() {
// //
const now = Date.now(); const now = Date.now();
if (this.isLoading || (now - this.lastRequestTime < 1000)) return; if (this.isLoading || (now - this.lastRequestTime < 1000)) return;
this.lastRequestTime = now; this.lastRequestTime = now;
// 使 // 使
if (this.currentPage === 1 && this.cachedNotices.length > 0) { if (this.currentPage === 1 && this.cachedNotices.length > 0) {
this.noticesList = [...this.cachedNotices]; this.noticesList = [...this.cachedNotices];
@ -100,29 +111,40 @@
setTimeout(() => this.fetchNotices(), 300); setTimeout(() => this.fetchNotices(), 300);
return; return;
} }
await this.fetchNotices(); await this.fetchNotices();
}, },
loadMore() {
if (!this.isLoading && this.currentPage < this.totalPages) {
console.log('触发加载更多,当前页:', this.currentPage);
this.currentPage += 1;
this.fetchNotices();
}
},
async fetchNotices() { async fetchNotices() {
this.isLoading = true; this.isLoading = true;
uni.showLoading({ title: '加载中...', mask: true }); uni.showLoading({
title: '加载中...',
mask: true
});
try { try {
const res = await get('/api/v1/apps/home/notices', { const res = await get('/api/v1/apps/home/notices', {
current: this.currentPage, current: this.currentPage,
pageSize: 10, pageSize: 10, // 10
}, { }, {
timeout: 5000 // timeout: 5000
}); });
if (res?.success) { if (res?.success) {
const processedData = res.data.map(item => ({ const processedData = res.data.map(item => ({
...item, ...item,
cover: this.processImageUrl(item.cover), cover: this.processImageUrl(item.cover),
desc: this.filterHtmlTags(item.desc) // HTMLXSS desc: this.filterHtmlTags(item.desc)
})); }));
if (this.currentPage === 1) { if (this.currentPage === 1) {
this.noticesList = processedData; this.noticesList = processedData;
// //
@ -134,7 +156,7 @@
} else { } else {
this.noticesList = this.noticesList.concat(processedData); this.noticesList = this.noticesList.concat(processedData);
} }
this.totalPages = Math.ceil(res.total / 10); this.totalPages = Math.ceil(res.total / 10);
} }
} catch (err) { } catch (err) {
@ -150,53 +172,29 @@
this.isLoading = false; this.isLoading = false;
} }
}, },
processImageUrl(url) { processImageUrl(url) {
if (!url) return '/static/images/default-cover.jpg'; if (!url) return '/static/images/default-cover.jpg';
return url.startsWith('http') ? url : IMAGE_BASE_URL + url; return url.startsWith('http') ? url : IMAGE_BASE_URL + url;
}, },
filterHtmlTags(str) { filterHtmlTags(str) {
if (!str) return ''; if (!str) return '';
return str.replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' '); return str.replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ');
}, },
handleImageError(index) { handleImageError(index) {
this.$set(this.noticesList, index, { this.$set(this.noticesList, index, {
...this.noticesList[index], ...this.noticesList[index],
cover: '/static/images/default-cover.jpg' cover: '/static/images/default-cover.jpg'
}); });
}, },
goNoticeDetail(id) { goNoticeDetail(id) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/serviceNoticeDetail/index?Id=${id}`, url: `/pages/serviceNoticeDetail/index?Id=${id}`,
animationType: 'slide-in-right' animationType: 'slide-in-right'
}); });
},
initScrollListener() {
this.onScroll = () => {
const scrollHeight = document.documentElement.scrollHeight;
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const clientHeight = document.documentElement.clientHeight;
// 200px
if (scrollTop + clientHeight >= scrollHeight - 200 &&
this.currentPage < this.totalPages &&
!this.isLoading) {
this.currentPage++;
this.getNotices();
}
};
window.addEventListener('scroll', this.onScroll);
},
removeScrollListener() {
if (this.onScroll) {
window.removeEventListener('scroll', this.onScroll);
}
} }
} }
}; };
@ -215,7 +213,7 @@
--shadow: 0 4rpx 12rpx rgba(59, 140, 255, 0.1); --shadow: 0 4rpx 12rpx rgba(59, 140, 255, 0.1);
--radius: 16rpx; --radius: 16rpx;
} }
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -223,24 +221,23 @@
background: linear-gradient(180deg, rgba(255, 241, 235, 0.8) 0%, rgba(192, 219, 250, 0.8) 100%); background: linear-gradient(180deg, rgba(255, 241, 235, 0.8) 0%, rgba(192, 219, 250, 0.8) 100%);
position: relative; position: relative;
} }
.content { .content {
flex: 1; flex: 1;
margin-top: 30rpx; // border-radius: 30rpx 30rpx 0 0;
border-radius: 30rpx 30rpx 0 0;
background-color: rgba(255, 255, 255, 0.85); background-color: rgba(255, 255, 255, 0.85);
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
.content-wrapper { .content-wrapper {
padding: 30rpx 0; padding: 30rpx 0;
.notice-list { .notice-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 24rpx; gap: 24rpx;
padding: 0 30rpx; padding: 0 30rpx;
.notice-item { .notice-item {
display: flex; display: flex;
background: var(--card-bg); background: var(--card-bg);
@ -249,12 +246,13 @@
transition: all 0.3s ease; transition: all 0.3s ease;
box-shadow: var(--shadow); box-shadow: var(--shadow);
border: 1rpx solid var(--border-color); border: 1rpx solid var(--border-color);
margin-bottom: 20rpx;
&:active { &:active {
transform: scale(0.98); transform: scale(0.98);
opacity: 0.9; opacity: 0.9;
} }
.notice-image { .notice-image {
width: 220rpx; width: 220rpx;
height: 220rpx; height: 220rpx;
@ -263,20 +261,20 @@
will-change: transform; will-change: transform;
image-rendering: -webkit-optimize-contrast; image-rendering: -webkit-optimize-contrast;
} }
.notice-content { .notice-content {
flex: 1; flex: 1;
padding: 24rpx; padding: 24rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.notice-title { .notice-title {
font-size: 32rpx; font-size: 32rpx;
font-weight: 600; font-weight: 600;
color: var(--secondary-color); color: var(--secondary-color);
margin-bottom: 12rpx; margin-bottom: 12rpx;
} }
.notice-description { .notice-description {
font-size: 26rpx; font-size: 26rpx;
color: var(--text-light); color: var(--text-light);
@ -284,17 +282,17 @@
margin-bottom: 16rpx; margin-bottom: 16rpx;
flex: 1; flex: 1;
} }
.notice-footer { .notice-footer {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.notice-date { .notice-date {
font-size: 24rpx; font-size: 24rpx;
color: var(--text-light); color: var(--text-light);
} }
.notice-more { .notice-more {
font-size: 24rpx; font-size: 24rpx;
color: var(--primary-color); color: var(--primary-color);
@ -302,47 +300,47 @@
} }
} }
} }
.load-more { .load-more {
text-align: center; text-align: center;
padding: 30rpx 0; padding: 30rpx 0;
color: var(--text-light); color: var(--text-light);
font-size: 26rpx; font-size: 26rpx;
} }
.empty-state { .empty-state {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 80rpx 0; padding: 80rpx 0;
.empty-image { .empty-image {
width: 200rpx; width: 200rpx;
height: 200rpx; height: 200rpx;
margin-bottom: 30rpx; margin-bottom: 30rpx;
opacity: 0.6; opacity: 0.6;
} }
.empty-text { .empty-text {
font-size: 28rpx; font-size: 28rpx;
color: var(--text-light); color: var(--text-light);
} }
} }
/* 骨架屏样式 */ /* 骨架屏样式 */
.skeleton-wrapper { .skeleton-wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 24rpx; gap: 24rpx;
.skeleton-item { .skeleton-item {
display: flex; display: flex;
background: #fff; background: #fff;
border-radius: var(--radius); border-radius: var(--radius);
overflow: hidden; overflow: hidden;
height: 220rpx; height: 220rpx;
.skeleton-image { .skeleton-image {
width: 220rpx; width: 220rpx;
height: 220rpx; height: 220rpx;
@ -350,25 +348,25 @@
background-size: 400% 100%; background-size: 400% 100%;
animation: loading 1.5s ease infinite; animation: loading 1.5s ease infinite;
} }
.skeleton-content { .skeleton-content {
flex: 1; flex: 1;
padding: 24rpx; padding: 24rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
.skeleton-line { .skeleton-line {
height: 32rpx; height: 32rpx;
background: #f2f2f2; background: #f2f2f2;
border-radius: 8rpx; border-radius: 8rpx;
margin-bottom: 16rpx; margin-bottom: 16rpx;
animation: loading 1.5s ease infinite; animation: loading 1.5s ease infinite;
&.short { &.short {
width: 60%; width: 60%;
} }
&.shorter { &.shorter {
width: 40%; width: 40%;
} }
@ -376,11 +374,12 @@
} }
} }
} }
@keyframes loading { @keyframes loading {
0% { 0% {
background-position: 100% 50%; background-position: 100% 50%;
} }
100% { 100% {
background-position: 0 50%; background-position: 0 50%;
} }
@ -388,7 +387,7 @@
} }
} }
} }
/* 通用工具类 */ /* 通用工具类 */
.line-clamp-1 { .line-clamp-1 {
display: -webkit-box; display: -webkit-box;
@ -396,7 +395,7 @@
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
} }
.line-clamp-2 { .line-clamp-2 {
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;

BIN
static/imgs/weather.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB