From d765a35a341f66b143f78fcf36d8f50a6c27baa9 Mon Sep 17 00:00:00 2001 From: "1054425342@qq.com" <1054425342@qq.com> Date: Tue, 23 Sep 2025 14:11:31 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/WaterfallLayout.vue | 669 +++++---- pages.json | 6 + pages/index/iSoul.vue | 18 +- pages/index/timeShopBank.vue | 290 ++-- pages/notes/detail.vue | 404 +++-- pages/notes/publish.vue | 397 ++--- static/js/CommonFunction.js | 2 +- static/js/request.js | 4 +- subPackages/haveFeeling/detail.vue | 72 +- subPackages/haveFeeling/detailAll.vue | 1113 ++++++++++++++ subPackages/haveFeeling/list.vue | 47 +- .../uni-file-picker/uni-file-picker.vue | 1295 +++++++++-------- 12 files changed, 2891 insertions(+), 1426 deletions(-) create mode 100644 subPackages/haveFeeling/detailAll.vue diff --git a/components/WaterfallLayout.vue b/components/WaterfallLayout.vue index 808376d..b5cee8b 100644 --- a/components/WaterfallLayout.vue +++ b/components/WaterfallLayout.vue @@ -1,299 +1,384 @@ \ No newline at end of file +.waterfall-layout { + width: 100%; + box-sizing: border-box; +} + +/* 空状态样式 */ +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 160rpx 40rpx; + text-align: center; +} + +.empty-icon { + width: 240rpx; + height: 240rpx; + margin-bottom: 40rpx; + opacity: 0.6; +} + +.empty-title { + font-size: 32rpx; + color: #666; + margin-bottom: 16rpx; + font-weight: 500; +} + +.empty-desc { + font-size: 28rpx; + color: #999; + line-height: 1.4; +} + +.waterfall-container { + display: flex; + gap: 16rpx; + padding: 0 20rpx; + box-sizing: border-box; +} + +.column { + flex: 1; + display: flex; + flex-direction: column; + gap: 16rpx; +} + +.waterfall-item { + box-sizing: border-box; + border-radius: 12rpx; + background: #fff; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08); + overflow: hidden; + transition: transform 0.2s ease; +} + +.waterfall-item:active { + transform: scale(0.98); +} + +.item-image { + width: 100%; + height: 476rpx; + object-fit: cover; +} + +.item-content { + padding: 16rpx; +} + +.item-title { + font-size: 28rpx; + font-weight: 600; + color: #333; + line-height: 1.3; + margin-bottom: 12rpx; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + text-overflow: ellipsis; +} + +.item-desc { + font-size: 24rpx; + color: #666; + line-height: 1.4; + margin-bottom: 16rpx; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + text-overflow: ellipsis; +} + +.item-tags { + display: flex; + flex-wrap: wrap; + gap: 8rpx; + margin-bottom: 16rpx; +} + +.tag { + padding: 4rpx 12rpx; + background: #f5f5f5; + color: #666; + font-size: 20rpx; + border-radius: 12rpx; + white-space: nowrap; +} + +.item-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 16rpx; +} + +.user-info { + display: flex; + align-items: center; + gap: 12rpx; +} + +.user-avatar { + width: 32rpx; + height: 32rpx; + border-radius: 50%; +} + +.username { + font-size: 22rpx; + color: #666; + width: 160rpx; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.like-info { + display: flex; + align-items: center; + gap: 6rpx; +} + +.like-icon { + font-size: 24rpx; + color: #ff6b6b; +} + +.like-count { + font-size: 22rpx; + color: #666; +} + diff --git a/pages.json b/pages.json index 4bd0e80..82d6ffe 100644 --- a/pages.json +++ b/pages.json @@ -272,6 +272,12 @@ "navigationBarTitleText": "订单详情" } }, + { + "path": "haveFeeling/detailAll", + "style": { + "navigationBarTitleText": "订单详情" + } + }, { "path": "haveFeeling/logistics", "style": { diff --git a/pages/index/iSoul.vue b/pages/index/iSoul.vue index b4c3c1a..abae9eb 100644 --- a/pages/index/iSoul.vue +++ b/pages/index/iSoul.vue @@ -234,6 +234,7 @@ - - - 欢迎来到「旅行时间行」,你的精神财富储蓄所。 - - - 在这里,你的每一次人文漫游、每一次灵感闪现,都值得被郑重记录。我们鼓励你分享高质量的图文笔记,将旅途中的美与感动,化为这座精神星球上的璀璨星辰。 - - - 为他人的美好驻足、点赞、留言,每一次真诚的互动,都是在为你的时间银行存入一笔宝贵的「精神货币」。这些资产不仅可以兑换独家福利与实体好物,更能为你解锁专属的荣誉身份,让你成为这座星球上最闪耀的共创者。 - - - 即刻发布你的第一篇笔记,开启你的财富积累之旅吧! - - - - + + 欢迎来到「旅行时间行」,你的精神财富储蓄所。 + + 在这里,你的每一次人文漫游、每一次灵感闪现,都值得被郑重记录。我们鼓励你分享高质量的图文笔记,将旅途中的美与感动,化为这座精神星球上的璀璨星辰。 + + + 为他人的美好驻足、点赞、留言,每一次真诚的互动,都是在为你的时间银行存入一笔宝贵的「精神货币」。这些资产不仅可以兑换独家福利与实体好物,更能为你解锁专属的荣誉身份,让你成为这座星球上最闪耀的共创者。 + + 即刻发布你的第一篇笔记,开启你的财富积累之旅吧! + + + @@ -44,7 +43,7 @@ - + - - @@ -126,94 +126,29 @@ export default { }, data() { return { - currentTab: 0, // 默认选中"笔记" + currentTab: 2, // 默认选中"笔记" tabs: [ { name: "笔记", id: "notes" }, { name: "关注", id: "follow" }, { name: "推荐", id: "recommend" }, ], - waterfallItems: [ - { - title: "生命的扶持|风景之旅", - image: "/uploads/20250824/2cf1f49920b911c9d14e4abf3b67a59c.png", - }, - { - title: "苏州丨园林之美 鱼戏莲叶间心随鱼鸟闲", - image: "/uploads/20250824/c209044a821630158f6e6771805682a7.png", - }, - { - title: "蘇州|你一句春不晚,我便出现在真江南", - image: "/uploads/20250824/74101a77233375625282209392dc69e3.png", - }, - { - title: "收好这天然氧吧", - image: "/uploads/20250824/e0ab7fd0483d05742451e8f10ab3ce24.png", - }, - ], + waterfallItems: [], + // 分页相关数据 + pageNum: 1, + pageSize: 10, + loading: false, + hasMore: true, autoAddEnabled: false, - // 图片URL数组 - images: [ - "/uploads/20250824/2cf1f49920b911c9d14e4abf3b67a59c.png", - "https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?auto=format&fit=crop&w=800", - "https://images.unsplash.com/photo-1441974231531-c6227db76b6e?auto=format&fit=crop&w=800", - "https://images.unsplash.com/photo-1469474968028-56623f02e42e?auto=format&fit=crop&w=800", - "https://images.unsplash.com/photo-1418065460487-3e41a6c84dc5?auto=format&fit=crop&w=800", - ], - // 用户头像数组 - avatars: [ - "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?auto=format&fit=crop&w=100", - "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?auto=format&fit=crop&w=100", - "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=crop&w=100", - "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?auto=format&fit=crop&w=100", - "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=crop&w=100", - ], - // 用户名数组 - usernames: [ - "杨璐摄影", - "旅行者小王", - "风景猎人", - "自然探索者", - "摄影师阿明", - ], - // 不同长度的标题 - shortTitles: ["城市风光", "自然美景", "湖光山色", "森林小径", "日出东方"], - mediumTitles: [ - "繁华都市的夜景与灯光", - "壮丽的山脉与蓝天白云", - "宁静的湖泊与秋日树木", - "蜿蜒的小路穿过金色森林", - "清晨第一缕阳光照亮大地", - ], - longTitles: [ - "现代都市天际线在黄昏时分展现出迷人的轮廓,灯火辉煌的建筑倒映在水面上", - "雄伟的山脉在云雾缭绕中若隐若现,展现出大自然的壮丽与神秘", - "平静如镜的湖面倒映着五彩斑斓的秋叶,构成一幅完美的自然画卷", - "阳光透过茂密的树叶,在铺满落叶的林间小路上投下斑驳的光影", - "清晨的太阳从地平线缓缓升起,金色的光芒洒满整个大地,带来新的一天", - ], - descriptions: [ - "探索城市中隐藏的美丽角落,发现不为人知的风景", - "大自然的鬼斧神工创造了无数令人惊叹的景观", - "水与山的完美结合,创造出宁静致远的意境", - "漫步在森林中,感受大自然的清新与宁静", - "日出时分的美景总能带给人们希望和力量", - ], - tagsList: [ - ["城市", "摄影", "旅行"], - ["自然", "山脉", "探险"], - ["湖泊", "秋天", "风景"], - ["森林", "小路", "自然"], - ["日出", "早晨", "美景"], - ], }; }, onLoad() { - this.initializeData(); this.userInfo = (uni.getStorageSync("userInfo") && JSON.parse(uni.getStorageSync("userInfo"))) || this.$store.state.user.userInfo || {}; + // 加载推荐列表数据 + this.getRecommendList(1); }, onShow() { if (this.userInfo && this.userInfo.id) { @@ -242,50 +177,46 @@ export default { }); }); }, - // 获取随机数据项 - getRandomItem() { - const titleType = - Math.random() > 0.5 - ? Math.random() > 0.5 - ? this.longTitles - : this.mediumTitles - : this.shortTitles; - - return { - id: Date.now() + Math.floor(Math.random() * 1000), - title: titleType[Math.floor(Math.random() * titleType.length)], - image: this.images[Math.floor(Math.random() * this.images.length)], - // description: - // this.descriptions[ - // Math.floor(Math.random() * this.descriptions.length) - // ], - // tags: this.tagsList[Math.floor(Math.random() * this.tagsList.length)], - // 新增用户信息 - user: { - avatar: this.avatars[Math.floor(Math.random() * this.avatars.length)], - name: this.usernames[ - Math.floor(Math.random() * this.usernames.length) - ], - }, - likes: Math.floor(Math.random() * 999) + 1, // 1-999的随机点赞数 - }; - }, - // 初始化数据 - initializeData() { - const initialItems = []; - for (let i = 0; i < 20; i++) { - initialItems.push(this.getRandomItem()); - } - // this.waterfallItems = initialItems; - }, + // 获取推荐列表数据 + getRecommendList(type = 1) { + if (this.loading) return; - // 添加随机项目 - addRandomItem() { - const newItem = this.getRandomItem(); - // this.waterfallItems.push(newItem); - }, + this.loading = true; + const params = { + pageNum: this.pageNum, + pageSize: this.pageSize, + type: type, // 0: 笔记tab, 1: 推荐tab + }; + this.Post(params, "/framework/note/list", "DES") + .then((res) => { + if (res.code === 200 && res.rows) { + const newItems = res.rows || []; + + if (this.pageNum === 1) { + // 首次加载或刷新 + this.waterfallItems = newItems; + } else { + // 加载更多 + this.waterfallItems.push(...newItems); + } + + // 判断是否还有更多数据 + this.hasMore = newItems.length === this.pageSize; + } + }) + .catch((error) => { + console.error("获取推荐列表失败:", error); + uni.showToast({ + title: "加载失败,请重试", + icon: "none", + }); + }) + .finally(() => { + this.loading = false; + }); + }, // 清空所有项目 clearAllItems() { uni.showModal({ @@ -301,9 +232,10 @@ export default { // 处理项目点击 handleItemClick(item) { + console.log(item); // 跳转到笔记详情页面 uni.navigateTo({ - url: `/pages/notes/detail`, + url: `/pages/notes/detail?id=${item.id}`, }); }, @@ -319,16 +251,17 @@ export default { // 处理自动添加请求 handleAutoAddRequest() { - this.addRandomItem(); + this.loadMoreItems(); }, // 加载更多项目(到达底部时调用) loadMoreItems() { - const newItems = []; - for (let i = 0; i < 10; i++) { - newItems.push(this.getRandomItem()); + if (!this.loading && this.hasMore) { + this.pageNum++; + // 根据当前tab传递不同的type: 0-笔记, 1-推荐 + const type = this.currentTab === 0 ? 0 : 1; + this.getRecommendList(type); } - // this.waterfallItems.push(...newItems); }, // Tab切换方法 @@ -341,8 +274,14 @@ export default { // 加载tab对应的内容 loadTabContent(tabId) { // 这里可以根据不同的tabId加载不同的数据 - // 重新初始化数据 - this.initializeData(); + if (tabId === "notes") { + // 笔记tab: 重置分页数据并加载笔记列表 + this.pageNum = 1; + this.waterfallItems = []; + this.hasMore = true; + this.getRecommendList(0); + } + // 推荐tab不需要重新加载数据,保持现有数据 }, }, }; @@ -498,6 +437,7 @@ page { .content-area { flex: 1; overflow: hidden; + padding: 10rpx 0; } .notes-content { @@ -521,20 +461,20 @@ page { color: #999; } } -.desc-box{ - padding: 0 20rpx; - color: #616161; - margin: 30rpx 0; - font-size: 24rpx; - padding: 0 40rpx; - view{ - margin-bottom: 20rpx; - &:nth-child(1){ - font-size: 24rpx; - font-weight: bold; - margin-bottom: 20rpx; - } - } +.desc-box { + padding: 0 20rpx; + color: #616161; + margin: 30rpx 0; + font-size: 24rpx; + padding: 0 40rpx; + view { + margin-bottom: 20rpx; + &:nth-child(1) { + font-size: 24rpx; + font-weight: bold; + margin-bottom: 20rpx; + } + } } /* 自定义样式已移至WaterfallLayout组件内部 */ diff --git a/pages/notes/detail.vue b/pages/notes/detail.vue index 8684178..29b1cc2 100644 --- a/pages/notes/detail.vue +++ b/pages/notes/detail.vue @@ -14,14 +14,10 @@ @change="swiperChange" > - + - + - - - - - - - {{ noteDetail.user.name }} - - - + + + + + {{ noteDetail.nickname }} + + + {{ noteDetail.title }} @@ -70,13 +64,29 @@ - {{ noteDetail.content }} + {{ noteDetail.content }} + + + #{{ tag }} + - - - - + + @@ -113,31 +123,41 @@ - - - - - + + + + + @@ -154,8 +174,8 @@ export default { return { noteId: "", commentText: "", - topBanner: ["/uploads/20250826/17356ed4dcdeedcd13de60ca28909d22.png"], - swiperIndex: 0, + topBanner: [], + swiperIndex: 0, noteDetail: { id: "", title: "", @@ -165,12 +185,8 @@ export default { likes: 0, isLiked: false, createTime: "", - user: { - id: "", - name: "", - avatar: "", - isFollowed: false, - }, + tagNames: [], + comments: [], }, }; @@ -180,20 +196,41 @@ export default { this.noteId = options.id; this.loadNoteDetail(); } else { - this.loadMockData(); + uni.showToast({ + title: "笔记ID不存在", + icon: "none", + }); + setTimeout(() => { + uni.navigateBack(); + }, 1500); } }, methods: { - swiperChange(e) { - this.swiperIndex = e.detail.current; - }, + swiperChange(e) { + this.swiperIndex = e.detail.current; + }, // 加载笔记详情 async loadNoteDetail() { try { uni.showLoading({ title: "加载中..." }); - // 模拟API调用 - const res = await this.getNoteDetail(this.noteId); - this.noteDetail = res.data; + // 调用真实API + const res = await this.Post( + { noteId: this.noteId }, + "/framework/note/getInfo/" + this.noteId, + "DES" + ); + if (res.code === 200) { + this.noteDetail = res.data; + this.noteDetail.tagNames = this.noteDetail.tagNames.split(","); + console.log(this.noteDetail.tagNames); + // 如果有图片,设置轮播图 + this.topBanner = this.noteDetail.coverImage.split(","); + } else { + uni.showToast({ + title: res.msg || "加载失败", + icon: "none", + }); + } } catch (error) { console.error("加载笔记详情失败:", error); uni.showToast({ @@ -232,8 +269,7 @@ export default { user: { id: "user002", name: "@小新", - avatar: - "/uploads/20250826/d68433653e8b8cceba9bc4a6ab2a394d.png", + avatar: "/uploads/20250826/d68433653e8b8cceba9bc4a6ab2a394d.png", }, }, { @@ -244,8 +280,7 @@ export default { user: { id: "user003", name: "Mr.曾", - avatar: - "/uploads/20250826/d68433653e8b8cceba9bc4a6ab2a394d.png", + avatar: "/uploads/20250826/d68433653e8b8cceba9bc4a6ab2a394d.png", }, }, ], @@ -255,24 +290,82 @@ export default { // 预览图片 previewImage(imageUrl) { uni.previewImage({ - urls: [imageUrl], + urls: this.topBanner, current: imageUrl, }); }, // 切换关注状态 - toggleFollow() { - this.noteDetail.user.isFollowed = !this.noteDetail.user.isFollowed; - uni.showToast({ - title: this.noteDetail.user.isFollowed ? "已关注" : "取消关注", - icon: "none", - }); + async toggleFollow() { + try { + const action = this.noteDetail.user.isFollowed ? "cancel" : "follow"; + const res = await this.Post( + { + method: "POST", + userId: this.noteDetail.user.id, + action: action, + }, + "/framework/user/follow", + "DES" + ); + + if (res.code === 200) { + this.noteDetail.user.isFollowed = !this.noteDetail.user.isFollowed; + uni.showToast({ + title: this.noteDetail.user.isFollowed ? "已关注" : "取消关注", + icon: "success", + }); + } else { + uni.showToast({ + title: + res.msg || (action === "follow" ? "关注失败" : "取消关注失败"), + icon: "none", + }); + } + } catch (error) { + console.error("关注操作失败:", error); + uni.showToast({ + title: "操作失败", + icon: "none", + }); + } }, // 切换点赞状态 - toggleLike() { - this.noteDetail.isLiked = !this.noteDetail.isLiked; - this.noteDetail.likes += this.noteDetail.isLiked ? 1 : -1; + async toggleLike() { + try { + const action = this.noteDetail.isLiked ? "cancel" : "like"; + const res = await this.Post( + { + method: "POST", + noteId: this.noteId, + action: action, + }, + "/framework/note/like", + "DES" + ); + + if (res.code === 200) { + this.noteDetail.isLiked = !this.noteDetail.isLiked; + this.noteDetail.likes += this.noteDetail.isLiked ? 1 : -1; + + // 可选:更新点赞数为接口返回的准确数值 + if (res.data && res.data.likeCount !== undefined) { + this.noteDetail.likes = res.data.likeCount; + } + } else { + uni.showToast({ + title: res.msg || (action === "like" ? "点赞失败" : "取消点赞失败"), + icon: "none", + }); + } + } catch (error) { + console.error("点赞操作失败:", error); + uni.showToast({ + title: "操作失败", + icon: "none", + }); + } }, // 提交评论 @@ -281,25 +374,42 @@ export default { return; } - const newComment = { - id: "comment" + Date.now(), - content: this.commentText, - createTime: new Date().toISOString(), - user: { - id: "current_user", - name: "我", - avatar: - "https://des.dayunyuanjian.cn/epicSoul/avatar-current.png", - }, - }; - - this.noteDetail.comments.unshift(newComment); - this.commentText = ""; - - uni.showToast({ - title: "评论成功", - icon: "success", - }); + try { + uni.showLoading({ title: "提交中..." }); + const res = await this.Post( + { + method: "POST", + noteId: this.noteId, + content: this.commentText, + }, + "/framework/note/comment/add", + "DES" + ); + + if (res.code === 200) { + // 评论成功后重新加载笔记详情,获取最新评论 + this.loadNoteDetail(); + this.commentText = ""; + + uni.showToast({ + title: "评论成功", + icon: "success", + }); + } else { + uni.showToast({ + title: res.msg || "评论失败", + icon: "none", + }); + } + } catch (error) { + console.error("提交评论失败:", error); + uni.showToast({ + title: "评论失败", + icon: "none", + }); + } finally { + uni.hideLoading(); + } }, // 格式化时间 @@ -311,17 +421,29 @@ export default { return `${year}/${month}/${day}`; }, - // 模拟API - 获取笔记详情 - async getNoteDetail(noteId) { - return new Promise((resolve) => { - setTimeout(() => { - this.loadMockData(); - resolve({ - code: 200, - data: this.noteDetail, - }); - }, 100); - }); + // 显示图片 + showImg(img) { + if (!img) return "/static/image/default-avatar.png"; + if (img.indexOf("https://") !== -1 || img.indexOf("http://") !== -1) { + return img; + } else { + return this.NEWAPIURLIMG + img; + } + }, + + // 处理标签点击 + handleTagClick(tag) { + console.log("标签点击:", tag); + // 可以根据需求跳转到标签相关页面或执行其他操作 + // uni.showToast({ + // title: `点击了标签: ${tag}`, + // icon: "none", + // }); + + // 如果需要跳转到标签相关页面,可以使用以下代码 + // uni.navigateTo({ + // url: `/pages/tags/detail?tag=${encodeURIComponent(tag)}` + // }); }, }, }; @@ -382,10 +504,10 @@ export default { font-size: 28rpx; color: #fff; font-weight: bold; - border: 2rpx solid #02fcfc; - color: #333333; -background-color: white; -padding: 12rpx 30rpx; + border: 2rpx solid #02fcfc; + color: #333333; + background-color: white; + padding: 12rpx 30rpx; &.followed { background: #ccc; } @@ -433,7 +555,21 @@ padding: 12rpx 30rpx; font-size: 30rpx; line-height: 1.6; color: #333; - font-weight: 500; + font-weight: 500; + word-break: break-all; + } + + .tag-names { + display: flex; + flex-wrap: wrap; + gap: 16rpx; + margin-top: 24rpx; + + .tag-link { + font-size: 28rpx; + color: #0066cc; + font-weight: 500; + } } } @@ -491,22 +627,22 @@ padding: 12rpx 30rpx; } } } -.comment-input-section-box{ - position: fixed; - bottom: 0; - left: 0; - right: 0; - z-index: 999; - box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1); - border-top: 1rpx solid #f0f0f0; - background: #fff; +.comment-input-section-box { + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 999; + box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1); + border-top: 1rpx solid #f0f0f0; + background: #fff; } // 底部评论输入 .comment-input-section { display: flex; align-items: center; padding: 24rpx 32rpx 0; - padding-bottom: max(env(safe-area-inset-bottom),24rpx); + padding-bottom: max(env(safe-area-inset-bottom), 24rpx); .comment-input { flex: 1; @@ -542,7 +678,7 @@ padding: 12rpx 30rpx; gap: 8rpx; .like-icon { - width:36rpx; + width: 36rpx; transition: color 0.3s; &.liked { color: #ff4757; @@ -552,7 +688,11 @@ padding: 12rpx 30rpx; .like-count { font-size: 30rpx; color: #666; - font-weight: bold; + font-weight: bold; + + &.liked-text { + color: #ff4757; + } } } } diff --git a/pages/notes/publish.vue b/pages/notes/publish.vue index 24c0223..1abfab8 100644 --- a/pages/notes/publish.vue +++ b/pages/notes/publish.vue @@ -4,32 +4,20 @@ - - - - - - × - - - - - + - - + -