diff --git a/app.json b/app.json
index 2f5a002..399dff5 100644
--- a/app.json
+++ b/app.json
@@ -15,7 +15,9 @@
"pages/profile/identify-history/index",
"pages/profile/badges/index",
"pages/profile/badges/level-detail/index",
- "pages/profile/badges/badge-wall/index"
+ "pages/profile/badges/badge-wall/index",
+ "pages/profile/favorites/index",
+ "pages/profile/posts/index"
],
"window": {
"backgroundTextStyle": "light",
diff --git a/assets/icons/arrow-left.png b/assets/icons/arrow-left.png
deleted file mode 100644
index da2775d..0000000
Binary files a/assets/icons/arrow-left.png and /dev/null differ
diff --git a/assets/icons/book-open.png b/assets/icons/book-open.png
deleted file mode 100644
index 270d9fe..0000000
Binary files a/assets/icons/book-open.png and /dev/null differ
diff --git a/assets/icons/calendar.png b/assets/icons/calendar.png
deleted file mode 100644
index d9186e0..0000000
Binary files a/assets/icons/calendar.png and /dev/null differ
diff --git a/assets/icons/camera.png b/assets/icons/camera.png
deleted file mode 100644
index 2c80455..0000000
Binary files a/assets/icons/camera.png and /dev/null differ
diff --git a/assets/icons/check.png b/assets/icons/check.png
deleted file mode 100644
index 3e02c2d..0000000
Binary files a/assets/icons/check.png and /dev/null differ
diff --git a/assets/icons/chevron-right.png b/assets/icons/chevron-right.png
deleted file mode 100644
index 33c08a5..0000000
Binary files a/assets/icons/chevron-right.png and /dev/null differ
diff --git a/assets/icons/crown.png b/assets/icons/crown.png
deleted file mode 100644
index 7988520..0000000
Binary files a/assets/icons/crown.png and /dev/null differ
diff --git a/assets/icons/droplets.png b/assets/icons/droplets.png
deleted file mode 100644
index 338cf4e..0000000
Binary files a/assets/icons/droplets.png and /dev/null differ
diff --git a/assets/icons/file-text.png b/assets/icons/file-text.png
deleted file mode 100644
index f98d984..0000000
Binary files a/assets/icons/file-text.png and /dev/null differ
diff --git a/assets/icons/heart.png b/assets/icons/heart.png
deleted file mode 100644
index d8bdf3f..0000000
Binary files a/assets/icons/heart.png and /dev/null differ
diff --git a/assets/icons/help-circle.png b/assets/icons/help-circle.png
deleted file mode 100644
index 0be30cc..0000000
Binary files a/assets/icons/help-circle.png and /dev/null differ
diff --git a/assets/icons/image.png b/assets/icons/image.png
deleted file mode 100644
index 900f3e1..0000000
Binary files a/assets/icons/image.png and /dev/null differ
diff --git a/assets/icons/lock.png b/assets/icons/lock.png
deleted file mode 100644
index f86b5cc..0000000
Binary files a/assets/icons/lock.png and /dev/null differ
diff --git a/assets/icons/medal.png b/assets/icons/medal.png
deleted file mode 100644
index a78b9cc..0000000
Binary files a/assets/icons/medal.png and /dev/null differ
diff --git a/assets/icons/scan-line.png b/assets/icons/scan-line.png
deleted file mode 100644
index c527065..0000000
Binary files a/assets/icons/scan-line.png and /dev/null differ
diff --git a/assets/icons/scissors.png b/assets/icons/scissors.png
deleted file mode 100644
index e42f020..0000000
Binary files a/assets/icons/scissors.png and /dev/null differ
diff --git a/assets/icons/search.png b/assets/icons/search.png
deleted file mode 100644
index ea69e1b..0000000
Binary files a/assets/icons/search.png and /dev/null differ
diff --git a/assets/icons/settings.png b/assets/icons/settings.png
deleted file mode 100644
index 149c1cf..0000000
Binary files a/assets/icons/settings.png and /dev/null differ
diff --git a/assets/icons/shield.png b/assets/icons/shield.png
deleted file mode 100644
index adc5c59..0000000
Binary files a/assets/icons/shield.png and /dev/null differ
diff --git a/assets/icons/shovel.png b/assets/icons/shovel.png
deleted file mode 100644
index 6b2f2d8..0000000
Binary files a/assets/icons/shovel.png and /dev/null differ
diff --git a/assets/icons/star.png b/assets/icons/star.png
deleted file mode 100644
index c167221..0000000
Binary files a/assets/icons/star.png and /dev/null differ
diff --git a/assets/icons/trophy.png b/assets/icons/trophy.png
deleted file mode 100644
index 391da9b..0000000
Binary files a/assets/icons/trophy.png and /dev/null differ
diff --git a/assets/icons/x.png b/assets/icons/x.png
deleted file mode 100644
index 662dc7f..0000000
Binary files a/assets/icons/x.png and /dev/null differ
diff --git a/assets/icons/zap.png b/assets/icons/zap.png
deleted file mode 100644
index 1a8d85f..0000000
Binary files a/assets/icons/zap.png and /dev/null differ
diff --git a/assets/react.svg b/assets/react.svg
deleted file mode 100644
index 6c87de9..0000000
--- a/assets/react.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/pages/community/index.js b/pages/community/index.js
index 15881fd..bc10d59 100644
--- a/pages/community/index.js
+++ b/pages/community/index.js
@@ -13,7 +13,9 @@ Page({
current: 1,
pageSize: 10,
hasMore: true,
- userInfo: null
+ userInfo: null,
+ scrollTop: 0,
+ isRefreshing: false
},
onLoad() {
@@ -33,9 +35,16 @@ Page({
}
},
- // Called by create post page
+ // Called by create post page or Pull Down
onRefresh() {
- this.fetchPosts(true);
+ this.setData({ isRefreshing: true });
+ this.fetchPosts(true).then(() => {
+ this.setData({ isRefreshing: false });
+ });
+ },
+
+ onTabItemTap() {
+ this.setData({ scrollTop: Math.random() * 0.01 });
},
onPullDownRefresh() {
@@ -60,7 +69,7 @@ Page({
try {
// Correct API Endpoint and Params
- const res = await request.post('/post/page', { current, pageSize });
+ const res = await request.post('/post/page', { current, pageSize, hasReviewed: 1 });
// Handle response structure: { code: 200, data: { list: [], ... } }
// OR if request.js unwraps it: { list: [], ... }
@@ -79,14 +88,16 @@ Page({
content: item.content,
images: (item.imgList || []).map(img => img.url),
time: item.createdAtStr || '刚刚',
- likes: (item.likeList || []).map(l => l.liker ? (l.liker.nickName || l.liker.name) : '花友'),
+ likes: item.hasLiked === 1 ? ['我'] : [],
comments: (item.commentList || []).map(c => ({
id: c.id,
user: c.commentator ? (c.commentator.nickName || c.commentator.name) : '花友',
content: c.content
})),
likedByMe: item.hasLiked === 1,
+ isFavorited: item.hasStar === 1,
likeCount: item.likeCount || 0,
+ stars: (item.starList || []).map(s => s.starer ? (s.starer.nickName || s.starer.name) : '花友'),
commentCount: item.commentCount || 0,
isExpanded: false
};
@@ -125,12 +136,7 @@ Page({
// Preview image in full screen
previewImage(e) {
const { url, urls } = e.currentTarget.dataset;
- const resolvedUrls = urls.map(img => {
- if (img.indexOf('http') === 0 || img.indexOf('wxfile') === 0) {
- return img;
- }
- return `/assets/${img}`;
- });
+ const resolvedUrls = urls.map(img => img);
wx.previewImage({
current: url,
@@ -169,10 +175,15 @@ Page({
try {
await request.get('/post/like', { id: postId, type });
- // Optimistic Update: Only toggle button state. Do NOT modify likes list text.
+ // Optimistic Update
const updatedPosts = this.data.posts.map(p => {
if (p.id === postId) {
- return { ...p, likedByMe: !p.likedByMe };
+ const liked = !p.likedByMe;
+ return {
+ ...p,
+ likedByMe: liked,
+ likes: liked ? ['我'] : []
+ };
}
return p;
});
@@ -192,6 +203,42 @@ Page({
}
},
+ // Collect post
+ async collectPost(e) {
+ const postId = e.currentTarget.dataset.id;
+ const post = this.data.posts.find(p => p.id === postId);
+ if (!post) return;
+
+ const type = post.isFavorited ? 2 : 1; // 1: Collect, 2: Cancel
+
+ try {
+ await request.get('/post/star', { id: postId, type });
+
+ // Optimistic Update
+ const updatedPosts = this.data.posts.map(p => {
+ if (p.id === postId) {
+ return { ...p, isFavorited: !p.isFavorited };
+ }
+ return p;
+ });
+
+ this.setData({
+ posts: updatedPosts,
+ displayedPosts: updatedPosts,
+ activePostId: null
+ });
+
+ // Refresh list to sync detailed data (like IDs if needed)
+ this.fetchPosts(true);
+
+ wx.showToast({ title: type === 1 ? '已收藏' : '已取消', icon: 'success' });
+
+ } catch (err) {
+ console.error('Collect failed', err);
+ wx.showToast({ title: '操作失败', icon: 'none' });
+ }
+ },
+
// Show comment input bar
showCommentInput(e) {
const postId = e.currentTarget.dataset.id;
diff --git a/pages/community/index.json b/pages/community/index.json
index 46387a6..489d5eb 100644
--- a/pages/community/index.json
+++ b/pages/community/index.json
@@ -1,5 +1,5 @@
{
- "navigationBarTitleText": "植友动态",
+ "navigationBarTitleText": "花友动态",
"usingComponents": {
"t-avatar": "tdesign-miniprogram/avatar/avatar",
"t-image": "tdesign-miniprogram/image/image",
diff --git a/pages/community/index.wxml b/pages/community/index.wxml
index 913e5c1..ed6c89d 100644
--- a/pages/community/index.wxml
+++ b/pages/community/index.wxml
@@ -15,6 +15,11 @@
enhanced="{{true}}"
show-scrollbar="{{false}}"
bindtap="hideActionPopup"
+ scroll-top="{{scrollTop}}"
+ bindscrolltolower="onReachBottom"
+ refresher-enabled="{{true}}"
+ bindrefresherrefresh="onRefresh"
+ refresher-triggered="{{isRefreshing}}"
>
@@ -49,10 +54,15 @@
+
+
+
+ 删除植物
+
diff --git a/pages/plant-detail/index.wxss b/pages/plant-detail/index.wxss
index 6df68ec..3cdcdca 100644
--- a/pages/plant-detail/index.wxss
+++ b/pages/plant-detail/index.wxss
@@ -811,3 +811,21 @@ page {
font-weight: 500;
color: #90A4AE;
}
+
+.delete-plant-box {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 12rpx;
+ padding: 24rpx;
+ margin-top: 40rpx;
+ background: #FFF;
+ border-radius: 24rpx;
+ box-shadow: 0 4rpx 12rpx rgba(239, 83, 80, 0.1);
+}
+
+.delete-text {
+ font-size: 28rpx;
+ color: #EF5350;
+ font-weight: 500;
+}
diff --git a/pages/profile/favorites/index.js b/pages/profile/favorites/index.js
new file mode 100644
index 0000000..bce09e8
--- /dev/null
+++ b/pages/profile/favorites/index.js
@@ -0,0 +1,34 @@
+import request from '../../../utils/request';
+
+Page({
+ data: {
+ favTab: 'all',
+ favorites: [],
+ filteredFavorites: []
+ },
+
+ onLoad() {
+ this.loadFavorites();
+ },
+
+ loadFavorites() {
+ // TODO: Call API
+ this.filterFavorites();
+ },
+
+ onFavTabChange(e) {
+ const val = e.currentTarget.dataset.value;
+ this.setData({ favTab: val }, () => {
+ this.filterFavorites();
+ });
+ },
+
+ filterFavorites() {
+ const { favorites, favTab } = this.data;
+ const filtered = favorites.filter(item => {
+ if (favTab === 'all') return true;
+ return item.type === favTab;
+ });
+ this.setData({ filteredFavorites: filtered });
+ }
+});
diff --git a/pages/profile/favorites/index.json b/pages/profile/favorites/index.json
new file mode 100644
index 0000000..892735f
--- /dev/null
+++ b/pages/profile/favorites/index.json
@@ -0,0 +1,7 @@
+{
+ "navigationBarTitleText": "我的收藏",
+ "usingComponents": {
+ "t-icon": "tdesign-miniprogram/icon/icon",
+ "t-image": "tdesign-miniprogram/image/image"
+ }
+}
\ No newline at end of file
diff --git a/pages/profile/favorites/index.wxml b/pages/profile/favorites/index.wxml
new file mode 100644
index 0000000..8d19ef4
--- /dev/null
+++ b/pages/profile/favorites/index.wxml
@@ -0,0 +1,27 @@
+
+
+ 全部
+ 植物
+ 文章
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+ {{item.meta}}
+
+
+
+
+
+
+ 暂无收藏内容
+
+
+
+
diff --git a/pages/profile/favorites/index.wxss b/pages/profile/favorites/index.wxss
new file mode 100644
index 0000000..eba094b
--- /dev/null
+++ b/pages/profile/favorites/index.wxss
@@ -0,0 +1,98 @@
+.favorites-page {
+ background: #F4F6F0;
+ height: 100vh;
+ padding: 24rpx;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.category-filter {
+ display: flex;
+ gap: 16rpx;
+ margin-bottom: 24rpx;
+}
+
+.filter-chip {
+ padding: 12rpx 32rpx;
+ background: #fff;
+ border: 2rpx solid transparent;
+ border-radius: 40rpx;
+ font-size: 26rpx;
+ color: #6B7280;
+ transition: all 0.2s;
+ font-weight: 500;
+}
+
+.filter-chip.active {
+ background: #333;
+ color: #fff;
+ font-weight: 600;
+ box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
+}
+
+.fav-scroll {
+ flex: 1;
+ height: 0;
+ width: 100%;
+}
+
+.fav-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20rpx;
+}
+
+.fav-card {
+ background: white;
+ border-radius: 20rpx;
+ overflow: hidden;
+ box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.03);
+ display: flex;
+ flex-direction: column;
+}
+
+.fav-img {
+ background: #f0f0f0;
+}
+
+.fav-info {
+ padding: 16rpx 20rpx;
+}
+
+.fav-name {
+ display: block;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: #1F2937;
+ margin-bottom: 8rpx;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.fav-meta-row {
+ display: flex;
+ align-items: center;
+ gap: 8rpx;
+}
+
+.fav-type {
+ font-size: 22rpx;
+ color: #9CA3AF;
+}
+
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 120rpx 0;
+}
+
+.empty-text {
+ font-size: 28rpx;
+ color: #9CA3AF;
+ margin-top: 16rpx;
+}
diff --git a/pages/profile/index.js b/pages/profile/index.js
index 1dd2e9c..8ea62da 100644
--- a/pages/profile/index.js
+++ b/pages/profile/index.js
@@ -29,7 +29,9 @@ Page({
myDrafts: [],
// App version
- appVersion: '1.0.0'
+ // App version
+ appVersion: '1.0.0',
+ scrollTop: 0
},
onLoad() {
@@ -44,6 +46,13 @@ Page({
this.loadUserInfo();
},
+ onTabItemTap() {
+ this.setData({
+ view: 'profile',
+ scrollTop: Math.random() * 0.01
+ });
+ },
+
// ======== User Info ========
loadUserInfo() {
request.get('/profile/detail').then(res => {
@@ -57,6 +66,7 @@ Page({
this.setData({
userName: res.nickname || '植物爱好者',
userAvatar: avatarUrl,
+ currentAvatarId: res.avatarId || (res.avatar ? res.avatar.id : ''),
// Stats
plantCount: res.plantCount || 0,
@@ -88,127 +98,16 @@ Page({
// ======== Navigation ========
- setView(e) {
- const view = e.currentTarget.dataset.view;
- this.setData({ view });
-
- if (view === 'favorites') {
- this.loadFavorites();
- } else if (view === 'posts') {
- this.loadMyPosts();
- this.loadDrafts();
- }
- },
-
goBack() {
this.setData({ view: 'profile' });
},
- // ======== Favorites ========
- loadFavorites() {
- // TODO: Call favorites API when available
- // request.get('/user/favorites').then(...)
- this.filterFavorites();
+ goToFavorites() {
+ wx.navigateTo({ url: '/pages/profile/favorites/index' });
},
- onFavTabChange(e) {
- this.setData({ favTab: e.detail.value }, () => {
- this.filterFavorites();
- });
- },
-
- filterFavorites() {
- const { favorites, favTab } = this.data;
- const filtered = favorites.filter(item => {
- if (favTab === 'all') return true;
- return item.type === favTab;
- });
- this.setData({ filteredFavorites: filtered });
- },
-
- // ======== Posts ========
- loadMyPosts() {
- request.post('/post/page', { current: 1, pageSize: 50, onlyMine: true }).then(res => {
- const records = res.records || res.list || [];
- const posts = records.map(item => {
- const publisher = item.publisher || {};
- const imgList = item.imgList || [];
- return {
- id: item.id,
- content: item.content || '',
- time: this._formatTime(item.createdAt || item.createTime),
- images: imgList.map(img => img.url),
- likes: item.likeList || [],
- comments: item.commentList || []
- };
- });
- this.setData({ myPublishedPosts: posts });
- }).catch(() => {
- this.setData({ myPublishedPosts: [] });
- });
- },
-
- loadDrafts() {
- try {
- const draft = wx.getStorageSync('post_draft');
- if (draft && (draft.content || (draft.images && draft.images.length > 0))) {
- this.setData({
- myDrafts: [{
- id: 'draft_1',
- content: draft.content || '',
- images: draft.images || [],
- selectedTopics: draft.selectedTopics || []
- }]
- });
- } else {
- this.setData({ myDrafts: [] });
- }
- } catch (e) {
- this.setData({ myDrafts: [] });
- }
- },
-
- onPostsTabChange(e) {
- this.setData({ postsTab: e.detail.value });
- },
-
- deletePost(e) {
- const postId = e.currentTarget.dataset.id;
- wx.showModal({
- title: '删除动态',
- content: '确定要删除这条动态吗?',
- confirmColor: '#EF5350',
- success: (res) => {
- if (!res.confirm) return;
- wx.showLoading({ title: '删除中...' });
- request.get('/post/delete', { id: postId }).then(() => {
- wx.hideLoading();
- this.loadMyPosts();
- wx.showToast({ title: '已删除', icon: 'success' });
- }).catch(() => {
- wx.hideLoading();
- wx.showToast({ title: '删除失败', icon: 'none' });
- });
- }
- });
- },
-
- editDraft() {
- wx.navigateTo({ url: '/pages/community/create/index' });
- },
-
- deleteDraft() {
- wx.showModal({
- title: '删除草稿',
- content: '确定要删除这份草稿吗?',
- confirmColor: '#EF5350',
- success: (res) => {
- if (!res.confirm) return;
- try { wx.removeStorageSync('post_draft'); } catch (e) { }
- this.setData({ myDrafts: [] });
- wx.showToast({ title: '已删除', icon: 'success' });
- }
- });
+ goToPosts() {
+ wx.navigateTo({ url: '/pages/profile/posts/index' });
},
// ======== Menu Actions ========
@@ -284,10 +183,12 @@ Page({
},
async saveProfile() {
- const { tempAvatar, tempNickname, userName, userAvatar } = this.data;
+ const { tempAvatar, tempNickname, userName, userAvatar, currentAvatarId } = this.data;
- // Check if anything changed
- const isNameChanged = tempNickname && tempNickname !== userName;
+ // Determine if there are changes
+ // tempNickname might be undefined if user didn't edit nickname input
+ const finalNickname = tempNickname !== undefined ? tempNickname : userName;
+ const isNameChanged = finalNickname !== userName;
const isAvatarChanged = tempAvatar && tempAvatar !== userAvatar;
if (!isNameChanged && !isAvatarChanged) {
@@ -295,61 +196,65 @@ Page({
return;
}
+ if (!finalNickname.trim()) {
+ wx.showToast({ title: '昵称不能为空', icon: 'none' });
+ return;
+ }
+
wx.showLoading({ title: '保存中...', mask: true });
try {
- const updatePayload = {};
+ let finalAvatarId = currentAvatarId;
- // 1. Upload avatar if changed
+ // Upload new avatar if changed
if (isAvatarChanged) {
const uploadRes = await request.upload(tempAvatar);
- // Correctly extract ID from file object based on known API response
- let fileId = '';
if (uploadRes && uploadRes.file && uploadRes.file.id) {
- fileId = uploadRes.file.id;
+ finalAvatarId = uploadRes.file.id;
} else if (uploadRes && uploadRes.id) {
- fileId = uploadRes.id;
- }
-
- if (fileId) {
- updatePayload.avatarId = fileId;
+ finalAvatarId = uploadRes.id;
+ } else {
+ throw new Error('Avatar upload failed, no ID returned');
}
}
- // 2. Set nickname if changed
- if (isNameChanged) {
- updatePayload.nickname = tempNickname;
- }
+ // Construct Full Payload
+ const updatePayload = {
+ nickname: finalNickname,
+ avatarId: finalAvatarId
+ };
- // 3. Call update API
- if (Object.keys(updatePayload).length > 0) {
- await request.post('/profile/update', updatePayload);
- }
+ // Call API
+ await request.post('/profile/update', updatePayload);
- wx.hideLoading();
-
- // 4. Update local state
+ // Update UI State
this.setData({
- userName: tempNickname || userName,
- userAvatar: tempAvatar || userAvatar, // Use tempAvatar for immediate display
+ userName: finalNickname,
+ userAvatar: tempAvatar || userAvatar,
+ currentAvatarId: finalAvatarId,
showProfileEditor: false
});
wx.showToast({ title: '资料已更新', icon: 'success' });
- // 5. Update globalData
+ // Update Global Data
const userInfo = app.globalData.userInfo || {};
- if (updatePayload.nickname) userInfo.name = updatePayload.nickname;
- if (updatePayload.avatarId) userInfo.avatarId = updatePayload.avatarId;
- // Also update URL if we have it locally?
- // Better to re-fetch profile to get canonical URL, but optimistic update is fine.
- userInfo.avatar = tempAvatar;
+ userInfo.nickname = finalNickname;
+ userInfo.name = finalNickname;
+ // Update avatar structure in global store too
+ if (isAvatarChanged) {
+ userInfo.avatar = { ...(userInfo.avatar || {}), url: tempAvatar, id: finalAvatarId };
+ }
+ userInfo.avatarId = finalAvatarId;
+
app.globalData.userInfo = userInfo;
+ wx.setStorageSync('userInfo', userInfo);
} catch (err) {
- wx.hideLoading();
console.error('Save profile failed', err);
wx.showToast({ title: '保存失败', icon: 'none' });
+ } finally {
+ wx.hideLoading();
}
},
diff --git a/pages/profile/index.wxml b/pages/profile/index.wxml
index 032fe05..dd3a2c7 100644
--- a/pages/profile/index.wxml
+++ b/pages/profile/index.wxml
@@ -1,70 +1,7 @@
-
-
-
-
- 我的收藏
-
-
-
- 全部
- 植物
- 文章
-
-
-
-
-
-
-
- {{item.name}}
-
-
- {{item.meta}}
-
-
-
-
-
- 暂无收藏内容
-
-
-
-
-
-
-
-
- 我的发布
-
-
-
-
- {{item.time}}
-
- {{item.content}}
-
-
-
-
-
-
-
-
-
-
-
-
+
关于我们
@@ -134,12 +71,12 @@
-
+
@@ -96,7 +93,11 @@
-
+
+
+
+
+
diff --git a/pages/wiki/index.wxss b/pages/wiki/index.wxss
index 1d06bde..4ecabd9 100644
--- a/pages/wiki/index.wxss
+++ b/pages/wiki/index.wxss
@@ -19,15 +19,71 @@
Usually easier to apply padding to the items or a wrapper inside scroll-view. */
.search-section {
- padding: 20rpx 40rpx 0;
+ padding: 24rpx 40rpx 0;
margin-bottom: 32rpx;
}
+.search-box-card {
+ background: #fff;
+ border-radius: 40rpx;
+ padding: 16rpx 20rpx;
+ box-shadow: 0 8rpx 24rpx rgba(85, 139, 47, 0.08); /* Green-tinted shadow */
+}
+
+/* Override TDesign Search */
+.search-input-bg {
+ background: #F4F6F0 !important; /* Light green-grey */
+ border-radius: 32rpx !important;
+ height: 80rpx !important;
+}
+.t-search__input-container {
+ height: 80rpx !important;
+}
+
+/* Category Scroll */
.category-scroll {
- display: flex;
- flex-wrap: wrap;
- padding: 0 40rpx;
- margin-bottom: 48rpx;
+ display: flex;
+ white-space: nowrap;
+ padding-left: 40rpx;
+ margin-bottom: 40rpx;
+ height: 88rpx;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+/* Hide scrollbar for webkit */
+.category-scroll::-webkit-scrollbar {
+ display: none;
+}
+
+.category-item {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 36rpx;
+ height: 72rpx;
+ background: #fff;
+ border-radius: 36rpx;
+ margin-right: 24rpx;
+ font-size: 28rpx;
+ color: #546E7A;
+ font-weight: 600;
+ box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.04);
+ transition: all 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
+ flex-shrink: 0;
+ border: 2rpx solid transparent; /* Reserve border space */
+}
+
+.category-item:active {
+ transform: scale(0.95);
+}
+
+.category-item.active {
+ background: #558B2F;
+ color: #fff;
+ font-weight: 700;
+ box-shadow: 0 8rpx 20rpx rgba(85, 139, 47, 0.3);
+ border-color: #558B2F;
}
.wiki-list {
@@ -59,6 +115,28 @@
box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.1);
flex-shrink: 0;
background: #f0f0f0;
+ position: relative;
+}
+
+.fav-icon-box {
+ position: absolute;
+ top: 10rpx;
+ right: 10rpx;
+ width: 56rpx;
+ height: 56rpx;
+ background: rgba(255, 255, 255, 0.85);
+ backdrop-filter: blur(4px);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 5;
+ box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
+}
+
+.fav-icon-box:active {
+ transform: scale(0.9);
+ transition: transform 0.1s;
}
.wiki-image image { width: 100%; height: 100%; display: block; }
.wiki-image-placeholder {
diff --git a/project.private.config.json b/project.private.config.json
index e1ffeca..1a50a2c 100644
--- a/project.private.config.json
+++ b/project.private.config.json
@@ -3,7 +3,7 @@
"projectname": "plant-mp",
"condition": {},
"setting": {
- "urlCheck": false,
+ "urlCheck": true,
"coverView": true,
"lazyloadPlaceholderEnable": false,
"skylineRenderEnable": false,
diff --git a/utils/mockData.js b/utils/constant.js
similarity index 72%
rename from utils/mockData.js
rename to utils/constant.js
index 3d61d92..b921069 100644
--- a/utils/mockData.js
+++ b/utils/constant.js
@@ -1,19 +1,18 @@
// 预置养护图标 - 模拟从后端加载
export const CARE_TASK_ICONS = [
- { id: 'water', name: '浇水', icon: 'rain-medium', color: '#2196F3', bgColor: '#E3F2FD' },
- { id: 'fertilize', name: '施肥', icon: 'gift', color: '#8BC34A', bgColor: '#F1F8E9' },
- { id: 'prune', name: '修剪', icon: 'cut', color: '#FF9800', bgColor: '#FFF3E0' },
- { id: 'repot', name: '换盆', icon: 'home', color: '#9C27B0', bgColor: '#F3E5F5' },
- { id: 'resoil', name: '换土', icon: 'load', color: '#757575', bgColor: '#F5F5F5' },
- { id: 'rotate', name: '转盆', icon: 'refresh', color: '#00BCD4', bgColor: '#E0F7FA' },
- { id: 'spray', name: '喷雾', icon: 'cloud', color: '#03A9F4', bgColor: '#E1F5FE' },
- { id: 'check', name: '检查', icon: 'search', color: '#4CAF50', bgColor: '#E8F5E9' },
- { id: 'sun', name: '晒太阳', icon: 'sunny', color: '#FFC107', bgColor: '#FFFDE7' },
- { id: 'move', name: '挪位置', icon: 'location', color: '#E91E63', bgColor: '#FCE4EC' },
- { id: 'medicine', name: '用药', icon: 'heart', color: '#F44336', bgColor: '#FFEBEE' },
- { id: 'other', name: '其他', icon: 'ellipsis', color: '#607D8B', bgColor: '#ECEFF1' },
-
+ { id: 'water', name: '浇水', icon: 'rain-medium', color: '#2196F3', bgColor: '#E3F2FD', targetAction: 'ACT_WATER' },
+ { id: 'fertilize', name: '施肥', icon: 'gift', color: '#8BC34A', bgColor: '#F1F8E9', targetAction: 'ACT_FERTILIZE' },
+ { id: 'prune', name: '修剪', icon: 'cut', color: '#FF9800', bgColor: '#FFF3E0', targetAction: 'ACT_PRUNE' },
+ { id: 'repot', name: '换盆', icon: 'home', color: '#9C27B0', bgColor: '#F3E5F5', targetAction: 'ACT_REPOT' },
+ { id: 'resoil', name: '换土', icon: 'load', color: '#757575', bgColor: '#F5F5F5', targetAction: 'ACT_RESOIL' },
+ { id: 'rotate', name: '转盆', icon: 'refresh', color: '#00BCD4', bgColor: '#E0F7FA', targetAction: 'ACT_ROTATE' },
+ { id: 'spray', name: '喷雾', icon: 'cloud', color: '#03A9F4', bgColor: '#E1F5FE', targetAction: 'ACT_SPRAY' },
+ { id: 'check', name: '检查', icon: 'search', color: '#4CAF50', bgColor: '#E8F5E9', targetAction: 'ACT_CHECK' },
+ { id: 'sun', name: '晒太阳', icon: 'sunny', color: '#FFC107', bgColor: '#FFFDE7', targetAction: 'ACT_SUN' },
+ { id: 'move', name: '挪位置', icon: 'location', color: '#E91E63', bgColor: '#FCE4EC', targetAction: 'ACT_MOVE' },
+ { id: 'medicine', name: '用药', icon: 'heart', color: '#F44336', bgColor: '#FFEBEE', targetAction: 'ACT_MEDICINE' },
+ { id: 'other', name: '其他', icon: 'ellipsis', color: '#607D8B', bgColor: '#ECEFF1', targetAction: 'ACT_OTHER' },
];
export const MOCK_BADGES = [
diff --git a/utils/request.js b/utils/request.js
index 7c84974..34dd597 100644
--- a/utils/request.js
+++ b/utils/request.js
@@ -270,8 +270,8 @@ class WxRequest {
// Initialize with default instance
const request = new WxRequest({
- baseUrl: 'http://192.168.0.184:8889',
- //baseUrl: 'https://go.sundynix.cn/api',
+ //baseUrl: 'http://192.168.0.184:8889',
+ baseUrl: 'https://go.sundynix.cn/api',
header: {
'Content-Type': 'application/json'
}